From 80a315f4da0f7ae718fb824a5af19d64c272d356 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Mon, 11 Aug 2025 17:18:00 -0400 Subject: [PATCH] Remove GNOME dependencies and make more desktop-neutral MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove gsettings-desktop-schemas dependency (GNOME-specific) - Replace gnome.post_install() with manual gtk4-update-icon-cache - Remove GNOME import from meson.build - Make autostart desktop file desktop-neutral (remove GSettings condition) - Add accessibility categories and keywords to desktop file 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- cthulhu-autostart.desktop.in | 8 +- distro-packages/Arch-Linux/PKGBUILD | 1 - .../Arch-Linux/pkg/cthulhu/.BUILDINFO | 2114 +++++++ distro-packages/Arch-Linux/pkg/cthulhu/.MTREE | Bin 0 -> 30876 bytes .../Arch-Linux/pkg/cthulhu/.PKGINFO | 54 + .../xdg/autostart/cthulhu-autostart.desktop | 59 + .../Arch-Linux/pkg/cthulhu/usr/bin/cthulhu | 294 + .../site-packages/cthulhu/__init__.py | 31 + .../python3.13/site-packages/cthulhu/acss.py | 130 + .../site-packages/cthulhu/action_presenter.py | 328 + .../site-packages/cthulhu/ax_collection.py | 153 + .../cthulhu/ax_event_synthesizer.py | 586 ++ .../site-packages/cthulhu/ax_object.py | 1381 ++++ .../site-packages/cthulhu/ax_selection.py | 129 + .../site-packages/cthulhu/ax_utilities.py | 211 + .../cthulhu/ax_utilities_collection.py | 1677 +++++ .../cthulhu/ax_utilities_role.py | 1467 +++++ .../cthulhu/ax_utilities_state.py | 366 ++ .../cthulhu/backends/__init__.py | 25 + .../cthulhu/backends/json_backend.py | 219 + .../site-packages/cthulhu/bookmarks.py | 328 + .../site-packages/cthulhu/braille.py | 2032 ++++++ .../cthulhu/braille_generator.py | 533 ++ .../cthulhu/braille_rolenames.py | 296 + .../site-packages/cthulhu/brlmon.py | 216 + .../site-packages/cthulhu/brltablenames.py | 165 + .../site-packages/cthulhu/caret_navigation.py | 462 ++ .../python3.13/site-packages/cthulhu/chat.py | 935 +++ .../site-packages/cthulhu/chnames.py | 822 +++ .../site-packages/cthulhu/cmdnames.py | 1162 ++++ .../site-packages/cthulhu/colornames.py | 758 +++ .../cthulhu/common_keyboardmap.py | 84 + .../site-packages/cthulhu/cthulhu.py | 1183 ++++ .../site-packages/cthulhu/cthulhuVersion.py | 27 + .../site-packages/cthulhu/cthulhu_bin.py | 278 + .../cthulhu/cthulhu_gtkbuilder.py | 162 + .../site-packages/cthulhu/cthulhu_gui_find.py | 256 + .../cthulhu/cthulhu_gui_navlist.py | 193 + .../cthulhu/cthulhu_gui_prefs.py | 3841 +++++++++++ .../cthulhu/cthulhu_gui_profile.py | 146 + .../site-packages/cthulhu/cthulhu_i18n.py | 91 + .../site-packages/cthulhu/cthulhu_platform.py | 53 + .../site-packages/cthulhu/cthulhu_state.py | 89 + .../cthulhu/date_and_time_presenter.py | 121 + .../site-packages/cthulhu/dbus_service.py | 862 +++ .../python3.13/site-packages/cthulhu/debug.py | 587 ++ .../cthulhu/desktop_keyboardmap.py | 72 + .../cthulhu/dynamic_api_manager.py | 87 + .../site-packages/cthulhu/event_manager.py | 1231 ++++ .../python3.13/site-packages/cthulhu/find.py | 267 + .../site-packages/cthulhu/flat_review.py | 1437 +++++ .../cthulhu/flat_review_presenter.py | 1193 ++++ .../site-packages/cthulhu/formatting.py | 1119 ++++ .../site-packages/cthulhu/generator.py | 1528 +++++ .../site-packages/cthulhu/guilabels.py | 944 +++ .../site-packages/cthulhu/highlighter.py | 219 + .../site-packages/cthulhu/input_event.py | 1162 ++++ .../cthulhu/input_event_manager.py | 431 ++ .../site-packages/cthulhu/keybindings.py | 590 ++ .../site-packages/cthulhu/keynames.py | 340 + .../site-packages/cthulhu/label_inference.py | 616 ++ .../cthulhu/laptop_keyboardmap.py | 75 + .../cthulhu/learn_mode_presenter.py | 386 ++ .../site-packages/cthulhu/liveregions.py | 608 ++ .../site-packages/cthulhu/logger.py | 77 + .../site-packages/cthulhu/mathsymbols.py | 2332 +++++++ .../site-packages/cthulhu/messages.py | 2865 +++++++++ .../site-packages/cthulhu/mouse_review.py | 683 ++ .../cthulhu/notification_presenter.py | 351 + .../site-packages/cthulhu/object_navigator.py | 331 + .../cthulhu/object_properties.py | 672 ++ .../site-packages/cthulhu/phonnames.py | 85 + .../site-packages/cthulhu/plugin.py | 107 + .../cthulhu/plugin_system_manager.py | 671 ++ .../cthulhu/plugins/AIAssistant/__init__.py | 22 + .../plugins/AIAssistant/ai_providers.py | 426 ++ .../cthulhu/plugins/AIAssistant/plugin.info | 7 + .../cthulhu/plugins/AIAssistant/plugin.py | 1832 ++++++ .../cthulhu/plugins/ByeCthulhu/__init__.py | 25 + .../cthulhu/plugins/ByeCthulhu/plugin.info | 8 + .../cthulhu/plugins/ByeCthulhu/plugin.py | 75 + .../cthulhu/plugins/Clipboard/__init__.py | 30 + .../cthulhu/plugins/Clipboard/plugin.info | 7 + .../cthulhu/plugins/Clipboard/plugin.py | 158 + .../plugins/DisplayVersion/__init__.py | 25 + .../plugins/DisplayVersion/plugin.info | 8 + .../cthulhu/plugins/DisplayVersion/plugin.py | 97 + .../cthulhu/plugins/HelloCthulhu/__init__.py | 25 + .../cthulhu/plugins/HelloCthulhu/plugin.info | 7 + .../cthulhu/plugins/HelloCthulhu/plugin.py | 113 + .../plugins/IndentationAudio/__init__.py | 14 + .../plugins/IndentationAudio/plugin.info | 8 + .../plugins/IndentationAudio/plugin.py | 478 ++ .../cthulhu/plugins/PluginManager/__init__.py | 14 + .../cthulhu/plugins/PluginManager/plugin.info | 8 + .../cthulhu/plugins/PluginManager/plugin.py | 406 ++ .../plugins/SimplePluginSystem/__init__.py | 25 + .../plugins/SimplePluginSystem/plugin.info | 9 + .../plugins/SimplePluginSystem/plugin.py | 407 ++ .../cthulhu/plugins/hello_world/__init__.py | 25 + .../cthulhu/plugins/hello_world/plugin.info | 8 + .../cthulhu/plugins/hello_world/plugin.py | 70 + .../cthulhu/plugins/self_voice/__init__.py | 25 + .../cthulhu/plugins/self_voice/plugin.info | 12 + .../cthulhu/plugins/self_voice/plugin.py | 189 + .../cthulhu/pronunciation_dict.py | 79 + .../cthulhu/punctuation_settings.py | 308 + .../site-packages/cthulhu/resource_manager.py | 374 ++ .../site-packages/cthulhu/script.py | 642 ++ .../site-packages/cthulhu/script_manager.py | 408 ++ .../site-packages/cthulhu/script_utilities.py | 5631 +++++++++++++++++ .../site-packages/cthulhu/scripts/__init__.py | 25 + .../cthulhu/scripts/apps/Banshee/__init__.py | 26 + .../cthulhu/scripts/apps/Banshee/script.py | 59 + .../scripts/apps/Banshee/script_utilities.py | 64 + .../cthulhu/scripts/apps/Eclipse/__init__.py | 26 + .../cthulhu/scripts/apps/Eclipse/script.py | 151 + .../scripts/apps/SeaMonkey/__init__.py | 31 + .../cthulhu/scripts/apps/SeaMonkey/script.py | 141 + .../scripts/apps/Thunderbird/__init__.py | 37 + .../scripts/apps/Thunderbird/script.py | 396 ++ .../scripts/apps/Thunderbird/spellcheck.py | 101 + .../cthulhu/scripts/apps/__init__.py | 44 + .../cthulhu/scripts/apps/epiphany/__init__.py | 32 + .../cthulhu/scripts/apps/epiphany/script.py | 56 + .../cthulhu/scripts/apps/evince/__init__.py | 30 + .../cthulhu/scripts/apps/evince/script.py | 123 + .../scripts/apps/evolution/__init__.py | 30 + .../apps/evolution/braille_generator.py | 76 + .../cthulhu/scripts/apps/evolution/script.py | 190 + .../apps/evolution/script_utilities.py | 130 + .../apps/evolution/speech_generator.py | 163 + .../cthulhu/scripts/apps/gajim/__init__.py | 26 + .../cthulhu/scripts/apps/gajim/script.py | 110 + .../scripts/apps/gcalctool/__init__.py | 30 + .../cthulhu/scripts/apps/gcalctool/script.py | 101 + .../cthulhu/scripts/apps/gedit/__init__.py | 36 + .../cthulhu/scripts/apps/gedit/script.py | 177 + .../cthulhu/scripts/apps/gedit/spellcheck.py | 89 + .../scripts/apps/gnome-documents/__init__.py | 31 + .../scripts/apps/gnome-documents/script.py | 80 + .../apps/gnome-documents/script_utilities.py | 49 + .../apps/gnome-documents/speech_generator.py | 46 + .../scripts/apps/gnome-shell/__init__.py | 26 + .../scripts/apps/gnome-shell/formatting.py | 73 + .../scripts/apps/gnome-shell/script.py | 158 + .../apps/gnome-shell/script_utilities.py | 138 + .../cthulhu/scripts/apps/kwin/__init__.py | 31 + .../cthulhu/scripts/apps/kwin/script.py | 50 + .../scripts/apps/kwin/script_utilities.py | 61 + .../apps/notification-daemon/__init__.py | 31 + .../apps/notification-daemon/script.py | 58 + .../scripts/apps/notify-osd/__init__.py | 31 + .../cthulhu/scripts/apps/notify-osd/script.py | 87 + .../cthulhu/scripts/apps/pidgin/__init__.py | 26 + .../cthulhu/scripts/apps/pidgin/chat.py | 70 + .../cthulhu/scripts/apps/pidgin/script.py | 231 + .../scripts/apps/pidgin/script_utilities.py | 188 + .../scripts/apps/pidgin/speech_generator.py | 97 + .../apps/smuxi-frontend-gnome/__init__.py | 26 + .../scripts/apps/smuxi-frontend-gnome/chat.py | 52 + .../apps/smuxi-frontend-gnome/script.py | 88 + .../cthulhu/scripts/apps/soffice/__init__.py | 26 + .../scripts/apps/soffice/braille_generator.py | 186 + .../scripts/apps/soffice/formatting.py | 90 + .../cthulhu/scripts/apps/soffice/script.py | 996 +++ .../scripts/apps/soffice/script_utilities.py | 815 +++ .../scripts/apps/soffice/speech_generator.py | 517 ++ .../scripts/apps/soffice/spellcheck.py | 149 + .../cthulhu/scripts/apps/xfwm4/__init__.py | 31 + .../cthulhu/scripts/apps/xfwm4/script.py | 80 + .../site-packages/cthulhu/scripts/default.py | 3455 ++++++++++ .../cthulhu/scripts/self_voicing.py | 76 + .../cthulhu/scripts/sleepmode/__init__.py | 31 + .../cthulhu/scripts/sleepmode/script.py | 225 + .../scripts/sleepmode/script_utilities.py | 59 + .../cthulhu/scripts/switcher/__init__.py | 31 + .../cthulhu/scripts/switcher/script.py | 146 + .../scripts/switcher/script_utilities.py | 86 + .../cthulhu/scripts/terminal/__init__.py | 30 + .../scripts/terminal/braille_generator.py | 43 + .../cthulhu/scripts/terminal/script.py | 169 + .../scripts/terminal/script_utilities.py | 234 + .../scripts/terminal/speech_generator.py | 43 + .../scripts/toolkits/Chromium/__init__.py | 30 + .../toolkits/Chromium/braille_generator.py | 71 + .../scripts/toolkits/Chromium/script.py | 468 ++ .../toolkits/Chromium/script_utilities.py | 438 ++ .../toolkits/Chromium/speech_generator.py | 103 + .../cthulhu/scripts/toolkits/GAIL/__init__.py | 26 + .../cthulhu/scripts/toolkits/GAIL/script.py | 126 + .../scripts/toolkits/GAIL/script_utilities.py | 84 + .../scripts/toolkits/Gecko/__init__.py | 27 + .../cthulhu/scripts/toolkits/Gecko/script.py | 369 ++ .../toolkits/Gecko/script_utilities.py | 337 + .../toolkits/J2SE-access-bridge/__init__.py | 27 + .../toolkits/J2SE-access-bridge/formatting.py | 69 + .../toolkits/J2SE-access-bridge/script.py | 200 + .../J2SE-access-bridge/script_utilities.py | 135 + .../J2SE-access-bridge/speech_generator.py | 170 + .../cthulhu/scripts/toolkits/Qt/__init__.py | 26 + .../cthulhu/scripts/toolkits/Qt/script.py | 91 + .../scripts/toolkits/Qt/script_utilities.py | 83 + .../cthulhu/scripts/toolkits/VCL.py | 37 + .../scripts/toolkits/WebKitGtk/__init__.py | 29 + .../toolkits/WebKitGtk/braille_generator.py | 110 + .../scripts/toolkits/WebKitGtk/script.py | 662 ++ .../toolkits/WebKitGtk/script_utilities.py | 289 + .../toolkits/WebKitGtk/speech_generator.py | 203 + .../cthulhu/scripts/toolkits/__init__.py | 34 + .../scripts/toolkits/clutter/__init__.py | 26 + .../scripts/toolkits/clutter/script.py | 42 + .../toolkits/clutter/script_utilities.py | 46 + .../cthulhu/scripts/toolkits/gtk/__init__.py | 27 + .../cthulhu/scripts/toolkits/gtk/script.py | 245 + .../scripts/toolkits/gtk/script_utilities.py | 243 + .../cthulhu/scripts/web/__init__.py | 30 + .../cthulhu/scripts/web/bookmarks.py | 143 + .../cthulhu/scripts/web/braille_generator.py | 308 + .../cthulhu/scripts/web/script.py | 2774 ++++++++ .../cthulhu/scripts/web/script_utilities.py | 5515 ++++++++++++++++ .../cthulhu/scripts/web/sound_generator.py | 128 + .../cthulhu/scripts/web/speech_generator.py | 851 +++ .../cthulhu/scripts/web/tutorial_generator.py | 52 + .../site-packages/cthulhu/settings.py | 447 ++ .../site-packages/cthulhu/settings_manager.py | 682 ++ .../site-packages/cthulhu/signal_manager.py | 83 + .../python3.13/site-packages/cthulhu/sound.py | 185 + .../site-packages/cthulhu/sound_generator.py | 379 ++ .../site-packages/cthulhu/speech.py | 324 + .../cthulhu/speech_and_verbosity_manager.py | 562 ++ .../site-packages/cthulhu/speech_generator.py | 2953 +++++++++ .../cthulhu/speechdispatcherfactory.py | 801 +++ .../site-packages/cthulhu/speechserver.py | 246 + .../site-packages/cthulhu/spellcheck.py | 342 + .../cthulhu/structural_navigation.py | 2424 +++++++ .../cthulhu/text_attribute_names.py | 784 +++ .../cthulhu/translation_context.py | 118 + .../cthulhu/translation_manager.py | 77 + .../cthulhu/tutorialgenerator.py | 799 +++ .../cthulhu/where_am_i_presenter.py | 496 ++ .../share/cthulhu/icons/cthulhu-splash.svg | 64 + .../usr/share/cthulhu/ui/cthulhu-find.ui | 359 ++ .../usr/share/cthulhu/ui/cthulhu-setup.ui | 3667 +++++++++++ .../icons/hicolor/16x16/apps/cthulhu.png | Bin 0 -> 685 bytes .../icons/hicolor/22x22/apps/cthulhu.png | Bin 0 -> 1082 bytes .../icons/hicolor/24x24/apps/cthulhu.png | Bin 0 -> 1095 bytes .../icons/hicolor/256x256/apps/cthulhu.png | Bin 0 -> 30247 bytes .../icons/hicolor/32x32/apps/cthulhu.png | Bin 0 -> 2265 bytes .../icons/hicolor/48x48/apps/cthulhu.png | Bin 0 -> 3781 bytes .../icons/hicolor/scalable/apps/cthulhu.svg | 1025 +++ .../symbolic/apps/cthulhu-symbolic.svg | 27 + .../share/locale/ab/LC_MESSAGES/cthulhu.mo | Bin 0 -> 27602 bytes .../share/locale/an/LC_MESSAGES/cthulhu.mo | Bin 0 -> 90073 bytes .../share/locale/ar/LC_MESSAGES/cthulhu.mo | Bin 0 -> 67018 bytes .../share/locale/ast/LC_MESSAGES/cthulhu.mo | Bin 0 -> 90157 bytes .../share/locale/be/LC_MESSAGES/cthulhu.mo | Bin 0 -> 94425 bytes .../share/locale/bg/LC_MESSAGES/cthulhu.mo | Bin 0 -> 163961 bytes .../share/locale/bn/LC_MESSAGES/cthulhu.mo | Bin 0 -> 118083 bytes .../share/locale/bn_IN/LC_MESSAGES/cthulhu.mo | Bin 0 -> 9285 bytes .../share/locale/bs/LC_MESSAGES/cthulhu.mo | Bin 0 -> 108213 bytes .../share/locale/ca/LC_MESSAGES/cthulhu.mo | Bin 0 -> 135837 bytes .../locale/ca@valencia/LC_MESSAGES/cthulhu.mo | Bin 0 -> 127374 bytes .../share/locale/ckb/LC_MESSAGES/cthulhu.mo | Bin 0 -> 18871 bytes .../share/locale/cs/LC_MESSAGES/cthulhu.mo | Bin 0 -> 134428 bytes .../share/locale/cy/LC_MESSAGES/cthulhu.mo | Bin 0 -> 28432 bytes .../share/locale/da/LC_MESSAGES/cthulhu.mo | Bin 0 -> 129169 bytes .../share/locale/de/LC_MESSAGES/cthulhu.mo | Bin 0 -> 134305 bytes .../share/locale/dz/LC_MESSAGES/cthulhu.mo | Bin 0 -> 75628 bytes .../share/locale/el/LC_MESSAGES/cthulhu.mo | Bin 0 -> 149866 bytes .../share/locale/en_CA/LC_MESSAGES/cthulhu.mo | Bin 0 -> 16351 bytes .../share/locale/en_GB/LC_MESSAGES/cthulhu.mo | Bin 0 -> 124885 bytes .../share/locale/eo/LC_MESSAGES/cthulhu.mo | Bin 0 -> 44083 bytes .../share/locale/es/LC_MESSAGES/cthulhu.mo | Bin 0 -> 133210 bytes .../share/locale/et/LC_MESSAGES/cthulhu.mo | Bin 0 -> 19087 bytes .../share/locale/eu/LC_MESSAGES/cthulhu.mo | Bin 0 -> 132274 bytes .../share/locale/fa/LC_MESSAGES/cthulhu.mo | Bin 0 -> 53328 bytes .../share/locale/fi/LC_MESSAGES/cthulhu.mo | Bin 0 -> 101858 bytes .../share/locale/fr/LC_MESSAGES/cthulhu.mo | Bin 0 -> 136100 bytes .../share/locale/fur/LC_MESSAGES/cthulhu.mo | Bin 0 -> 10744 bytes .../share/locale/ga/LC_MESSAGES/cthulhu.mo | Bin 0 -> 3178 bytes .../share/locale/gl/LC_MESSAGES/cthulhu.mo | Bin 0 -> 133241 bytes .../share/locale/gu/LC_MESSAGES/cthulhu.mo | Bin 0 -> 33664 bytes .../share/locale/he/LC_MESSAGES/cthulhu.mo | Bin 0 -> 97299 bytes .../share/locale/hi/LC_MESSAGES/cthulhu.mo | Bin 0 -> 113069 bytes .../share/locale/hr/LC_MESSAGES/cthulhu.mo | Bin 0 -> 105779 bytes .../share/locale/hu/LC_MESSAGES/cthulhu.mo | Bin 0 -> 137407 bytes .../share/locale/id/LC_MESSAGES/cthulhu.mo | Bin 0 -> 127543 bytes .../share/locale/is/LC_MESSAGES/cthulhu.mo | Bin 0 -> 6554 bytes .../share/locale/it/LC_MESSAGES/cthulhu.mo | Bin 0 -> 132306 bytes .../share/locale/ja/LC_MESSAGES/cthulhu.mo | Bin 0 -> 68120 bytes .../share/locale/ka/LC_MESSAGES/cthulhu.mo | Bin 0 -> 199929 bytes .../share/locale/kab/LC_MESSAGES/cthulhu.mo | Bin 0 -> 7782 bytes .../share/locale/kk/LC_MESSAGES/cthulhu.mo | Bin 0 -> 14512 bytes .../share/locale/kn/LC_MESSAGES/cthulhu.mo | Bin 0 -> 17452 bytes .../share/locale/ko/LC_MESSAGES/cthulhu.mo | Bin 0 -> 34389 bytes .../share/locale/lt/LC_MESSAGES/cthulhu.mo | Bin 0 -> 135116 bytes .../share/locale/lv/LC_MESSAGES/cthulhu.mo | Bin 0 -> 128499 bytes .../share/locale/mai/LC_MESSAGES/cthulhu.mo | Bin 0 -> 45226 bytes .../share/locale/mk/LC_MESSAGES/cthulhu.mo | Bin 0 -> 114061 bytes .../share/locale/ml/LC_MESSAGES/cthulhu.mo | Bin 0 -> 91588 bytes .../share/locale/mr/LC_MESSAGES/cthulhu.mo | Bin 0 -> 19415 bytes .../share/locale/ms/LC_MESSAGES/cthulhu.mo | Bin 0 -> 122977 bytes .../share/locale/nb/LC_MESSAGES/cthulhu.mo | Bin 0 -> 111386 bytes .../share/locale/ne/LC_MESSAGES/cthulhu.mo | Bin 0 -> 160601 bytes .../share/locale/nl/LC_MESSAGES/cthulhu.mo | Bin 0 -> 126849 bytes .../share/locale/nn/LC_MESSAGES/cthulhu.mo | Bin 0 -> 53117 bytes .../share/locale/oc/LC_MESSAGES/cthulhu.mo | Bin 0 -> 100378 bytes .../share/locale/or/LC_MESSAGES/cthulhu.mo | Bin 0 -> 47589 bytes .../share/locale/pa/LC_MESSAGES/cthulhu.mo | Bin 0 -> 70778 bytes .../share/locale/pl/LC_MESSAGES/cthulhu.mo | Bin 0 -> 137893 bytes .../share/locale/pt/LC_MESSAGES/cthulhu.mo | Bin 0 -> 132160 bytes .../share/locale/pt_BR/LC_MESSAGES/cthulhu.mo | Bin 0 -> 131984 bytes .../share/locale/ro/LC_MESSAGES/cthulhu.mo | Bin 0 -> 135819 bytes .../share/locale/ru/LC_MESSAGES/cthulhu.mo | Bin 0 -> 172249 bytes .../share/locale/rw/LC_MESSAGES/cthulhu.mo | Bin 0 -> 558 bytes .../share/locale/si/LC_MESSAGES/cthulhu.mo | Bin 0 -> 6577 bytes .../share/locale/sk/LC_MESSAGES/cthulhu.mo | Bin 0 -> 126237 bytes .../share/locale/sl/LC_MESSAGES/cthulhu.mo | Bin 0 -> 135154 bytes .../share/locale/sq/LC_MESSAGES/cthulhu.mo | Bin 0 -> 11493 bytes .../share/locale/sr/LC_MESSAGES/cthulhu.mo | Bin 0 -> 161173 bytes .../locale/sr@latin/LC_MESSAGES/cthulhu.mo | Bin 0 -> 124739 bytes .../share/locale/sv/LC_MESSAGES/cthulhu.mo | Bin 0 -> 130155 bytes .../share/locale/ta/LC_MESSAGES/cthulhu.mo | Bin 0 -> 128905 bytes .../share/locale/te/LC_MESSAGES/cthulhu.mo | Bin 0 -> 127236 bytes .../share/locale/tg/LC_MESSAGES/cthulhu.mo | Bin 0 -> 54363 bytes .../share/locale/th/LC_MESSAGES/cthulhu.mo | Bin 0 -> 113790 bytes .../share/locale/tr/LC_MESSAGES/cthulhu.mo | Bin 0 -> 130563 bytes .../share/locale/ug/LC_MESSAGES/cthulhu.mo | Bin 0 -> 99716 bytes .../share/locale/uk/LC_MESSAGES/cthulhu.mo | Bin 0 -> 171944 bytes .../share/locale/vi/LC_MESSAGES/cthulhu.mo | Bin 0 -> 97079 bytes .../share/locale/zh_CN/LC_MESSAGES/cthulhu.mo | Bin 0 -> 122370 bytes .../share/locale/zh_HK/LC_MESSAGES/cthulhu.mo | Bin 0 -> 83896 bytes .../share/locale/zh_TW/LC_MESSAGES/cthulhu.mo | Bin 0 -> 89693 bytes .../cthulhu/usr/share/man/man1/cthulhu.1.gz | Bin 0 -> 3041 bytes distro-packages/Arch-Linux/src/cthulhu | 1 + meson.build | 7 +- 337 files changed, 100663 insertions(+), 8 deletions(-) create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/.BUILDINFO create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/.MTREE create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/.PKGINFO create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/etc/xdg/autostart/cthulhu-autostart.desktop create mode 100755 distro-packages/Arch-Linux/pkg/cthulhu/usr/bin/cthulhu create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/acss.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/action_presenter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_collection.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_event_synthesizer.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_object.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_selection.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_collection.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_role.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_state.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/json_backend.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/bookmarks.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_rolenames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brlmon.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brltablenames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/caret_navigation.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chat.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chnames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cmdnames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/colornames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/common_keyboardmap.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhuVersion.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_bin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gtkbuilder.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_find.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_navlist.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_prefs.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_profile.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_i18n.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_platform.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_state.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/date_and_time_presenter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dbus_service.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/debug.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/desktop_keyboardmap.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dynamic_api_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/event_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/find.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review_presenter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/formatting.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/guilabels.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/highlighter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keybindings.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keynames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/label_inference.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/laptop_keyboardmap.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/learn_mode_presenter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/liveregions.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/logger.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mathsymbols.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/messages.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mouse_review.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/notification_presenter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_navigator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_properties.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/phonnames.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin_system_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/ai_providers.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.info create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/pronunciation_dict.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/punctuation_settings.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/resource_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/spellcheck.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/spellcheck.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/formatting.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/chat.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/chat.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/formatting.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/spellcheck.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/default.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/self_voicing.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/formatting.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/VCL.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/__init__.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/bookmarks.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/braille_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script_utilities.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/sound_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/tutorial_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/signal_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_and_verbosity_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_generator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechdispatcherfactory.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechserver.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/spellcheck.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/structural_navigation.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/text_attribute_names.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_context.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_manager.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/tutorialgenerator.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/where_am_i_presenter.py create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/icons/cthulhu-splash.svg create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-find.ui create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-setup.ui create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/16x16/apps/cthulhu.png create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/22x22/apps/cthulhu.png create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/24x24/apps/cthulhu.png create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/256x256/apps/cthulhu.png create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/32x32/apps/cthulhu.png create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/48x48/apps/cthulhu.png create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/scalable/apps/cthulhu.svg create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/symbolic/apps/cthulhu-symbolic.svg create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ab/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/an/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ar/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ast/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/be/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bg/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bn/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bn_IN/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bs/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ca/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ca@valencia/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ckb/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/cs/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/cy/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/da/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/de/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/dz/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/el/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/en_CA/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/en_GB/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/eo/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/es/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/et/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/eu/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fa/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fi/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fr/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fur/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ga/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/gl/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/gu/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/he/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/hi/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/hr/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/hu/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/id/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/is/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/it/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ja/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ka/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kab/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kk/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kn/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ko/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/lt/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/lv/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mai/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mk/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ml/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mr/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ms/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nb/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ne/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nl/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nn/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/oc/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/or/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pa/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pl/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pt/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pt_BR/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ro/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ru/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/rw/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/si/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sk/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sl/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sq/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sr/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sr@latin/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sv/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ta/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/te/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/tg/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/th/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/tr/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ug/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/uk/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/vi/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/zh_CN/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/zh_HK/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/zh_TW/LC_MESSAGES/cthulhu.mo create mode 100644 distro-packages/Arch-Linux/pkg/cthulhu/usr/share/man/man1/cthulhu.1.gz create mode 160000 distro-packages/Arch-Linux/src/cthulhu diff --git a/cthulhu-autostart.desktop.in b/cthulhu-autostart.desktop.in index 7c56e93..2269fbc 100644 --- a/cthulhu-autostart.desktop.in +++ b/cthulhu-autostart.desktop.in @@ -3,7 +3,9 @@ Type=Application Name=Cthulhu Screen Reader Exec=cthulhu NoDisplay=true -AutostartCondition=GSettings org.gnome.desktop.a11y.applications screen-reader-enabled +# Desktop-neutral autostart - no GNOME-specific conditions +# Users can enable/disable via their desktop environment's accessibility settings +# or by adding/removing this file from ~/.config/autostart/ X-GNOME-AutoRestart=true -#X-GNOME-Autostart-Phase=Initialization -OnlyShowIn=GNOME;MATE;Unity;Cinnamon; +Categories=Accessibility; +Keywords=screen;reader;accessibility;speech;braille; diff --git a/distro-packages/Arch-Linux/PKGBUILD b/distro-packages/Arch-Linux/PKGBUILD index 78cb30c..2646d17 100644 --- a/distro-packages/Arch-Linux/PKGBUILD +++ b/distro-packages/Arch-Linux/PKGBUILD @@ -37,7 +37,6 @@ depends=( python-pyautogui # Desktop integration - gsettings-desktop-schemas hicolor-icon-theme libwnck3 pango diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/.BUILDINFO b/distro-packages/Arch-Linux/pkg/cthulhu/.BUILDINFO new file mode 100644 index 0000000..9caa7ec --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/.BUILDINFO @@ -0,0 +1,2114 @@ +format = 2 +pkgname = cthulhu +pkgbase = cthulhu +pkgver = 2025.08.11-1 +pkgarch = any +pkgbuild_sha256sum = e93f5713e098ed0d03e7a88e0ae93bd90bf0ca69769680ee4b4d5ae5cbae77c6 +packager = Unknown Packager +builddate = 1754945422 +builddir = /home/storm/devel/cthulhu/distro-packages/Arch-Linux +startdir = /home/storm/devel/cthulhu/distro-packages/Arch-Linux +buildtool = makepkg +buildtoolver = 7.0.0 +buildenv = !distcc +buildenv = color +buildenv = !ccache +buildenv = check +buildenv = !sign +options = strip +options = docs +options = !libtool +options = !staticlibs +options = emptydirs +options = zipman +options = purge +options = !debug +options = !lto +installed = 7zip-24.09-3-x86_64 +installed = a52dec-0.8.0-2-x86_64 +installed = aalib-1.4rc5-19-x86_64 +installed = aaxtomp3-git-1.3.r56.ge66c51d-1-any +installed = abseil-cpp-20250512.1-1-x86_64 +installed = acl-2.3.2-1-x86_64 +installed = adwaita-cursors-48.1-1-any +installed = adwaita-fonts-49.0-2-any +installed = adwaita-icon-theme-48.1-1-any +installed = adwaita-icon-theme-legacy-46.2-3-any +installed = allegro-5.2.10.1-4-x86_64 +installed = almanac-0.4.3-1-x86_64 +installed = alsa-card-profiles-1:1.4.7-1-x86_64 +installed = alsa-firmware-1.2.4-4-any +installed = alsa-lib-1.2.14-1-x86_64 +installed = alsa-plugins-1:1.2.12-4-x86_64 +installed = alsa-topology-conf-1.2.5.1-4-any +installed = alsa-ucm-conf-1.2.14-2-any +installed = alsa-utils-1.2.14-1-x86_64 +installed = amd-ucode-20250708-1-any +installed = android-tools-35.0.2-17-x86_64 +installed = android-udev-20250525-1-any +installed = angelscript-2.36.1-1-x86_64 +installed = ansible-core-2.19.0-1-any +installed = antiword-0.37-11-x86_64 +installed = aom-3.12.1-1-x86_64 +installed = appimage-appimage-13-1-x86_64 +installed = appstream-1.0.5-2-x86_64 +installed = arch-install-scripts-29-1-any +installed = archiso-85-1-any +installed = archlinux-keyring-20250716-1-any +installed = argon2-20190702-6-x86_64 +installed = asciidoc-10.2.1-2-any +installed = aspell-0.60.8.1-2-x86_64 +installed = aspell-en-2020.12.07-2-x86_64 +installed = at-spi2-core-2.56.4-1-x86_64 +installed = attr-2.5.2-1-x86_64 +installed = audacious-4.4.2-1-x86_64 +installed = audacious-plugins-4.4.2-4-x86_64 +installed = audiofile-0.3.6-10-x86_64 +installed = audit-4.0.5-1-x86_64 +installed = aur-out-of-date-3.2.0-1-x86_64 +installed = autoconf-2.72-1-any +installed = automake-1.18.1-1-any +installed = autopep8-1:2.3.2-1-any +installed = avahi-1:0.9rc2-1-x86_64 +installed = baresip-3.24.0-1-x86_64 +installed = barnard-git-1:r14.657ff1d-1-x86_64 +installed = base-3-2-any +installed = base-devel-1-2-any +installed = bash-5.3.3-2-x86_64 +installed = bash-completion-2.16.0-1-any +installed = bashblog-git-3-2-any +installed = bashtuner-2019.04.20-1-any +installed = bat-0.25.0-4-x86_64 +installed = bc-1.08.2-1-x86_64 +installed = bind-9.20.11-1-x86_64 +installed = binutils-2.45+r8+g09be88bfb653-1-x86_64 +installed = binwalk-3.1.0-1-x86_64 +installed = birthday-1.6.2-2-x86_64 +installed = bison-3.8.2-8-x86_64 +installed = blas-3.12.1-2-x86_64 +installed = blasphemer-wad-0.1.8-1-any +installed = bluefish-2.2.17-1-x86_64 +installed = blueman-2.4.6-1-x86_64 +installed = bluez-5.83-1-x86_64 +installed = bluez-libs-5.83-1-x86_64 +installed = bluez-utils-5.83-1-x86_64 +installed = boost-libs-1.88.0-3-x86_64 +installed = botamusique-7.2.3-1-x86_64 +installed = botan2-2.19.5-2-x86_64 +installed = brave-bin-1:1.80.125-1-x86_64 +installed = brltty-6.7-5-x86_64 +installed = brotli-1.1.0-3-x86_64 +installed = bubblewrap-0.11.0-1-x86_64 +installed = bullet-3.25-6-x86_64 +installed = bzip2-1.0.8-6-x86_64 +installed = c-ares-1.34.5-1-x86_64 +installed = ca-certificates-20240618-1-any +installed = ca-certificates-mozilla-3.114-1-x86_64 +installed = ca-certificates-utils-20240618-1-any +installed = cabextract-1.11-2-x86_64 +installed = cairo-1.18.4-1-x86_64 +installed = cairo-perl-1.109-6-x86_64 +installed = calc-2.15.1.1-1-x86_64 +installed = calibre-8.7.0-1-x86_64 +installed = capstone-5.0.6-1-x86_64 +installed = catdoc-0.95-6-x86_64 +installed = cblas-3.12.1-2-x86_64 +installed = ccid-1.6.2-1-x86_64 +installed = cddb_get-2.28-6-any +installed = cdparanoia-10.2-9-x86_64 +installed = cdrtools-3.02a09-6-x86_64 +installed = check-0.15.2-3-x86_64 +installed = chmlib-0.40-8-x86_64 +installed = chromaprint-1.5.1-10-x86_64 +installed = cifs-utils-7.4-1-x86_64 +installed = clang-20.1.8-1-x86_64 +installed = claude-code-1.0.70-1-any +installed = clipster-2.1.1-1-any +installed = clucene-2.3.3.4-16-x86_64 +installed = cmake-4.0.3-1-x86_64 +installed = cmus-2.12.0-3-x86_64 +installed = code-1.102.3-1-x86_64 +installed = colord-1.4.8-1-x86_64 +installed = colord-sane-1.4.8-1-x86_64 +installed = compiler-rt-20.1.8-1-x86_64 +installed = confuse-3.3-4-x86_64 +installed = containerd-2.1.4-1-x86_64 +installed = copyparty-1.18.10-1-any +installed = coreutils-9.7-1-x86_64 +installed = cowsay-3.8.4-1-any +installed = cpio-2.15-3-x86_64 +installed = cppdap-1.58.0-2-x86_64 +installed = cracklib-2.10.3-1-x86_64 +installed = croc-1:10.2.4-1-x86_64 +installed = cronie-1.7.2-1-x86_64 +installed = cryptsetup-2.8.0-1-x86_64 +installed = cthulhu-2025.08.11-1-any +installed = cuda-12.9.1-2-x86_64 +installed = cudnn-9.11.0.98-3-x86_64 +installed = cups-2:2.4.12-2-x86_64 +installed = cups-filters-2.0.1-2-x86_64 +installed = cups-pdf-3.0.2-1-x86_64 +installed = cups-pk-helper-0.2.7-2-x86_64 +installed = curl-8.15.0-1-x86_64 +installed = cython-3.1.2-1-x86_64 +installed = dav1d-1.5.1-1-x86_64 +installed = davfs2-1.7.1-3-x86_64 +installed = db5.3-5.3.28-5-x86_64 +installed = dbus-1.16.2-1-x86_64 +installed = dbus-broker-37-2-x86_64 +installed = dbus-broker-units-37-2-x86_64 +installed = dbus-glib-0.114-1-x86_64 +installed = dconf-0.40.0-3-x86_64 +installed = debootstrap-1.0.141-1-any +installed = debugedit-5.2-1-x86_64 +installed = default-cursors-3-1-any +installed = desktop-file-utils-0.28-1-x86_64 +installed = deutex-5.2.3-1-x86_64 +installed = device-mapper-2.03.34-1-x86_64 +installed = dex2jar-2.4-1-any +installed = dhcpcd-10.2.4-1-x86_64 +installed = dialog-1:1.3_20250116-1-x86_64 +installed = diffutils-3.12-2-x86_64 +installed = discount-3.0.0.d-1-x86_64 +installed = distro-info-1.11-1-x86_64 +installed = distro-info-data-0.63-1-any +installed = djmount-0.71.1-0-x86_64 +installed = djvulibre-3.5.29-1-x86_64 +installed = dmidecode-3.6-1-x86_64 +installed = dnsmasq-2.91-1-x86_64 +installed = dnssec-anchors-20250524-1-any +installed = docbook-xml-4.5-11-any +installed = docbook-xsl-1.79.2-9-any +installed = docker-1:28.3.3-1-x86_64 +installed = dopewars-1.6.2-3-x86_64 +installed = dos2unix-7.5.2-2-x86_64 +installed = dosfstools-4.2-5-x86_64 +installed = dotconf-1.4.1-1-x86_64 +installed = double-conversion-3.3.1-1-x86_64 +installed = downgrade-11.5.2-1-any +installed = dracut-108-1-x86_64 +installed = dtc-1.7.2-4-x86_64 +installed = duktape-2.7.0-7-x86_64 +installed = dumb-2.0.3-4-x86_64 +installed = dunst-1.12.2-1-x86_64 +installed = dvisvgm-3.5-2-x86_64 +installed = e2fsprogs-1.47.3-1-x86_64 +installed = edk2-ovmf-202411-1-any +installed = efibootmgr-18-3-x86_64 +installed = efivar-39-1-x86_64 +installed = egl-gbm-1.1.2.1-1-x86_64 +installed = egl-wayland-4:1.1.19-1-x86_64 +installed = egl-x11-1.0.2-1-x86_64 +installed = eglexternalplatform-1.2.1-1-any +installed = electron35-35.7.2-1-x86_64 +installed = element-0.46.6-2-x86_64 +installed = enchant-2.8.12-1-x86_64 +installed = epr-git-2.4.15.r154.723c77d-1-any +installed = erofs-utils-1.8.10-1-x86_64 +installed = espeak-ng-1.52.0-1-x86_64 +installed = exo-4.20.0-2-x86_64 +installed = expat-2.7.1-1-x86_64 +installed = extract_url-1.6.2-1-any +installed = ezquake-3.6.6-1-x86_64 +installed = ezstream-1.0.1-2-x86_64 +installed = faac-1.31.1-1-x86_64 +installed = faad2-2.11.2-1-x86_64 +installed = fakeroot-1.37.1.2-1-x86_64 +installed = farstream-0.2.9-3-x86_64 +installed = fastfetch-2.49.0-1-x86_64 +installed = feh-3.10.3-1-x86_64 +installed = fenrir-git-1:r3411.98b9c56a-1-any +installed = festival-2.5.0-5-x86_64 +installed = ffcall-2.5-1-x86_64 +installed = ffmpeg-2:7.1.1-5-x86_64 +installed = fftw-3.3.10-7-x86_64 +installed = file-5.46-4-x86_64 +installed = filesystem-2025.05.03-1-any +installed = findutils-4.10.0-3-x86_64 +installed = firefox-141.0-1-x86_64 +installed = flac-1.5.0-1-x86_64 +installed = flashrom-1.6.0-1-x86_64 +installed = flex-2.6.4-5-x86_64 +installed = flite-2.2-2-x86_64 +installed = fluidsynth-2.4.7-1-x86_64 +installed = fmt-11.2.0-1-x86_64 +installed = fontconfig-2:2.17.1-1-x86_64 +installed = foomatic-db-engine-5:20200131-2-x86_64 +installed = fortune-mod-3.24.0-1-x86_64 +installed = fortune-mod-confucius-20200529-1-any +installed = freedm-0.13.0-1-any +installed = freedoom-0.13.0-1-any +installed = freeglut-3.6.0-2-x86_64 +installed = freetype2-2.13.3-3-x86_64 +installed = frei0r-plugins-2.3.3-4-x86_64 +installed = fribidi-1.0.16-2-x86_64 +installed = frotz-dumb-2.55-1-x86_64 +installed = fuse-common-3.17.1-1-x86_64 +installed = fuse2-2.9.9-5-x86_64 +installed = fuse3-3.17.1-1-x86_64 +installed = fwupd-2.0.13-1-x86_64 +installed = fwupd-efi-1.7-1-any +installed = fzf-0.65.1-1-x86_64 +installed = gamemode-1.8.2-1-x86_64 +installed = garcon-4.20.0-2-x86_64 +installed = gawk-5.3.2-1-x86_64 +installed = gc-8.2.8-2-x86_64 +installed = gcc-15.1.1+r500+gb1b8d8ce3eea-1-x86_64 +installed = gcc-libs-15.1.1+r500+gb1b8d8ce3eea-1-x86_64 +installed = gcc14-14.3.1+r25+g42e99e057bd7-1-x86_64 +installed = gcc14-libs-14.3.1+r25+g42e99e057bd7-1-x86_64 +installed = gcr-3.41.2-2-x86_64 +installed = gcr-4-4.4.0.1-1-x86_64 +installed = gd-2.3.3-8-x86_64 +installed = gdb-16.3-1-x86_64 +installed = gdb-common-16.3-1-x86_64 +installed = gdbm-1.25-1-x86_64 +installed = gdk-pixbuf2-2.42.12-2-x86_64 +installed = gdown-5.2.0-1-any +installed = gemini-cli-0.1.17-1-x86_64 +installed = gendesk-1.0.10-1-x86_64 +installed = geoclue-2.7.2-1-x86_64 +installed = geoip-1.6.12-3-x86_64 +installed = geoip-database-20250129-1-any +installed = gettext-0.26-1-x86_64 +installed = gfxstream-0.1.2-2-x86_64 +installed = ghc-libs-9.4.8-1-x86_64 +installed = ghostscript-10.05.1-2-x86_64 +installed = giflib-5.2.2-2-x86_64 +installed = git-2.50.1-3-x86_64 +installed = git-lfs-3.7.0-1-x86_64 +installed = git-smb-1.3-1-any +installed = gjs-2:1.84.2-1-x86_64 +installed = glew-2.2.0-7-x86_64 +installed = glib-networking-1:2.80.1-1-x86_64 +installed = glib-perl-1.329.4-3-x86_64 +installed = glib2-2.84.3-1-x86_64 +installed = glib2-devel-2.84.3-1-x86_64 +installed = glibc-2.42+r3+gbc13db739377-1-x86_64 +installed = glm-1.0.1-1-x86_64 +installed = glslang-1:1.4.321.0-1-x86_64 +installed = glu-9.0.3-2-x86_64 +installed = gmp-6.3.0-2-x86_64 +installed = gnu-free-fonts-20120503-8-any +installed = gnu-netcat-0.7.1-11-x86_64 +installed = gnulib-l10n-20241231-1-any +installed = gnupg-2.4.8-1-x86_64 +installed = gnustep-base-1.31.1-1-x86_64 +installed = gnutls-3.8.10-1-x86_64 +installed = go-2:1.24.5-1-x86_64 +installed = gobject-introspection-1.84.0-2-x86_64 +installed = gobject-introspection-runtime-1.84.0-2-x86_64 +installed = gpaste-45.3-1-x86_64 +installed = gperftools-2.17-1-x86_64 +installed = gpgme-2.0.0-1-x86_64 +installed = gpgmepp-2.0.0-2-x86_64 +installed = gpm-1.20.7.r38.ge82d1a6-6-x86_64 +installed = gpodder-3.11.5-1-any +installed = gptfdisk-1.0.10-1-x86_64 +installed = graphene-1.10.8-2-x86_64 +installed = graphite-1:1.3.14-5-x86_64 +installed = graphviz-13.1.1-1-x86_64 +installed = grep-3.12-2-x86_64 +installed = groff-1.23.0-7-x86_64 +installed = grub-2:2.12.r292.g73d1c959-1-x86_64 +installed = gsettings-desktop-schemas-48.0-1-any +installed = gsettings-system-schemas-48.0-1-any +installed = gsfonts-20200910-5-any +installed = gsm-1.0.22-2-x86_64 +installed = gspell-1.14.0-2-x86_64 +installed = gssdp-1.6.4-1-x86_64 +installed = gst-libav-1.26.4-1-x86_64 +installed = gst-plugin-pipewire-1:1.4.7-1-x86_64 +installed = gst-plugins-bad-1.26.4-1-x86_64 +installed = gst-plugins-bad-libs-1.26.4-1-x86_64 +installed = gst-plugins-base-1.26.4-1-x86_64 +installed = gst-plugins-base-libs-1.26.4-1-x86_64 +installed = gst-plugins-good-1.26.4-1-x86_64 +installed = gst-plugins-ugly-1.26.4-1-x86_64 +installed = gstreamer-1.26.4-1-x86_64 +installed = gtest-1.17.0-1-x86_64 +installed = gtk-layer-shell-0.9.2-1-x86_64 +installed = gtk-update-icon-cache-1:4.18.6-1-x86_64 +installed = gtk-vnc-1.5.0-1-x86_64 +installed = gtk2-2.24.33-5-x86_64 +installed = gtk3-1:3.24.49-2-x86_64 +installed = gtk4-1:4.18.6-1-x86_64 +installed = gtksourceview3-1:3.24.11+r30+gd880929f-1-x86_64 +installed = gtksourceview4-4.8.4-2-x86_64 +installed = gtkspell-2.0.16-9-x86_64 +installed = gts-0.7.6.121130-3-x86_64 +installed = guile-3.0.10-1-x86_64 +installed = gum-0.16.2-1-x86_64 +installed = gupnp-1:1.6.9-1-x86_64 +installed = gupnp-igd-1.6.0-2-x86_64 +installed = gzdoom-4.11.3-2-x86_64 +installed = gzip-1.14-2-x86_64 +installed = handbrake-1.9.2-3-x86_64 +installed = harfbuzz-11.3.3-1-x86_64 +installed = harfbuzz-icu-11.3.3-1-x86_64 +installed = haskell-aeson-2.1.2.1-115-x86_64 +installed = haskell-ansi-terminal-1.0.2-28-x86_64 +installed = haskell-ansi-terminal-types-0.11.5-68-x86_64 +installed = haskell-ansi-wl-pprint-1.0.2-12-x86_64 +installed = haskell-assoc-1.1.1-39-x86_64 +installed = haskell-attoparsec-0.14.4-111-x86_64 +installed = haskell-base-compat-0.12.3-1-x86_64 +installed = haskell-base-compat-batteries-0.12.3-20-x86_64 +installed = haskell-base-orphans-0.9.1-21-x86_64 +installed = haskell-bifunctors-5.6.1-3-x86_64 +installed = haskell-colour-2.3.6-278-x86_64 +installed = haskell-comonad-5.0.9-57-x86_64 +installed = haskell-contravariant-1.5.5-5-x86_64 +installed = haskell-data-fix-0.3.4-9-x86_64 +installed = haskell-diff-0.4.1-111-x86_64 +installed = haskell-distributive-0.6.2.1-251-x86_64 +installed = haskell-dlist-1.0-287-x86_64 +installed = haskell-erf-2.0.0.0-26-x86_64 +installed = haskell-fgl-5.8.3.0-36-x86_64 +installed = haskell-foldable1-classes-compat-0.1-201-x86_64 +installed = haskell-generically-0.1.1-24-x86_64 +installed = haskell-hashable-1.4.4.0-105-x86_64 +installed = haskell-indexed-traversable-0.1.4-112-x86_64 +installed = haskell-indexed-traversable-instances-0.1.2-61-x86_64 +installed = haskell-integer-logarithms-1.0.4-14-x86_64 +installed = haskell-onetuple-0.4.2-54-x86_64 +installed = haskell-optparse-applicative-0.18.1.0-16-x86_64 +installed = haskell-os-string-2.0.7-46-x86_64 +installed = haskell-prettyprinter-1.7.1-232-x86_64 +installed = haskell-prettyprinter-ansi-terminal-1.1.3-242-x86_64 +installed = haskell-prettyprinter-compat-ansi-wl-pprint-1.0.2-13-x86_64 +installed = haskell-primitive-0.9.0.0-4-x86_64 +installed = haskell-quickcheck-2.14.3-164-x86_64 +installed = haskell-random-1.2.1.2-105-x86_64 +installed = haskell-regex-base-0.94.0.3-2-x86_64 +installed = haskell-regex-tdfa-1.3.2.4-18-x86_64 +installed = haskell-scientific-0.3.7.0-154-x86_64 +installed = haskell-semialign-1.3-49-x86_64 +installed = haskell-semigroupoids-6.0.1-31-x86_64 +installed = haskell-splitmix-0.1.0.5-93-x86_64 +installed = haskell-statevar-1.2.2-4-x86_64 +installed = haskell-strict-0.5-90-x86_64 +installed = haskell-tagged-0.8.9-2-x86_64 +installed = haskell-tasty-1.4.3-152-x86_64 +installed = haskell-text-short-0.1.6-38-x86_64 +installed = haskell-th-abstraction-0.5.0.0-1-x86_64 +installed = haskell-these-1.2.1-29-x86_64 +installed = haskell-time-compat-1.9.6.1-137-x86_64 +installed = haskell-transformers-compat-0.7.2-3-x86_64 +installed = haskell-unordered-containers-0.2.20-70-x86_64 +installed = haskell-uuid-types-1.0.6-28-x86_64 +installed = haskell-vector-0.13.2.0-34-x86_64 +installed = haskell-vector-stream-0.1.0.1-3-x86_64 +installed = haskell-witherable-0.4.2-166-x86_64 +installed = hdf5-1.14.6-5-x86_64 +installed = hicolor-icon-theme-0.18-1-any +installed = hidapi-0.15.0-1-x86_64 +installed = highway-1.2.0-1-x86_64 +installed = hplip-1:3.25.2-1-x86_64 +installed = hugo-0.148.2-1-x86_64 +installed = hunspell-1.7.2-2-x86_64 +installed = hunspell-en_us-2020.12.07-5-any +installed = hwdata-0.397-1-any +installed = hwloc-2.12.1-1-x86_64 +installed = hydrogen-1.2.6-1-x86_64 +installed = hydrogen-drumkits-flac-20220929-4-any +installed = hyphen-2.8.8-6-x86_64 +installed = i3-wm-4.24-1-x86_64 +installed = iana-etc-20250612-1-any +installed = ibus-1.5.32-1-x86_64 +installed = icecast-2.4.4-5-x86_64 +installed = icu-76.1-1-x86_64 +installed = ijs-0.35-6-x86_64 +installed = imagemagick-7.1.2.0-2-x86_64 +installed = imath-3.1.12-4-x86_64 +installed = imlib2-1.12.5-1-x86_64 +installed = iniparser-4.2.6-2-x86_64 +installed = inotify-tools-4.23.9.0-2-x86_64 +installed = intel-oneapi-common-2024.1.0-1-any +installed = intel-oneapi-compiler-shared-runtime-libs-2025.0.4-2-x86_64 +installed = intel-oneapi-openmp-2025.0.4-1-x86_64 +installed = intel-oneapi-tcm-1.2.0-3-x86_64 +installed = iproute2-6.16.0-2-x86_64 +installed = iptables-1:1.8.11-2-x86_64 +installed = iputils-20250605-1-x86_64 +installed = ipython-9.4.0-1-any +installed = irqbalance-1.9.4-2-x86_64 +installed = irssi-1.4.5-5-x86_64 +installed = iso-codes-4.18.0-1-any +installed = ispell-3.4.06-1-x86_64 +installed = itstool-1:2.0.7-3-any +installed = iw-6.9-1-x86_64 +installed = jack-matchmaker-0.11.0-3-any +installed = jadx-1.5.1-1-any +installed = jami-daemon-20240812-4-x86_64 +installed = jami-qt-20241126.0-1-x86_64 +installed = jansson-2.14.1-1-x86_64 +installed = jasper-4.2.5-1-x86_64 +installed = java-environment-common-3-6-any +installed = java-runtime-common-3-6-any +installed = jbig2dec-0.20-1-x86_64 +installed = jbigkit-2.1-8-x86_64 +installed = jdk-openjdk-24.0.2.u12-1-x86_64 +installed = jdk8-openjdk-8.462.u08-1-x86_64 +installed = jemalloc-1:5.3.0-5-x86_64 +installed = jq-1.8.1-1-x86_64 +installed = jre8-openjdk-8.462.u08-1-x86_64 +installed = jre8-openjdk-headless-8.462.u08-1-x86_64 +installed = js128-128.13.0-2-x86_64 +installed = json-c-0.18-2-x86_64 +installed = json-glib-1.10.6-1-x86_64 +installed = jsoncpp-1.9.6-3-x86_64 +installed = just-1.42.4-1-x86_64 +installed = jxrlib-0.2.4-2-x86_64 +installed = kbd-2.8.0-1-x86_64 +installed = kdsingleapplication-1.2.0-1-x86_64 +installed = keychain-2.9.5-1-any +installed = keyutils-1.6.3-3-x86_64 +installed = klick-0.14.2-3-x86_64 +installed = kmod-34.2-1-x86_64 +installed = krb5-1.21.3-2-x86_64 +installed = kubo-0.36.0-2-x86_64 +installed = l-smash-2.14.5-4-x86_64 +installed = ladspa-1.17-5-x86_64 +installed = lame-3.100-5-x86_64 +installed = lapack-3.12.1-2-x86_64 +installed = lcms2-2.17-1-x86_64 +installed = ldb-2:4.22.3-1-x86_64 +installed = leafpad-0.8.19-3-x86_64 +installed = leancrypto-1.5.1-1-x86_64 +installed = leptonica-1.85.0-2-x86_64 +installed = less-1:679-1-x86_64 +installed = level-zero-loader-1.22.5-1-x86_64 +installed = lftp-4.9.3-1-x86_64 +installed = lib32-aalib-1.4rc5-5-x86_64 +installed = lib32-acl-2.3.2-1-x86_64 +installed = lib32-alsa-lib-1.2.14-1-x86_64 +installed = lib32-alsa-plugins-1.2.12-1-x86_64 +installed = lib32-at-spi2-core-2.56.4-1-x86_64 +installed = lib32-audit-4.0.5-1-x86_64 +installed = lib32-brotli-1.1.0-1-x86_64 +installed = lib32-bzip2-1.0.8-4-x86_64 +installed = lib32-cairo-1.18.4-1-x86_64 +installed = lib32-cdparanoia-10.2-5-x86_64 +installed = lib32-curl-8.15.0-1-x86_64 +installed = lib32-dbus-1.16.2-1-x86_64 +installed = lib32-duktape-2.7.0-7-x86_64 +installed = lib32-e2fsprogs-1.47.3-1-x86_64 +installed = lib32-expat-2.7.1-1-x86_64 +installed = lib32-flac-1.5.0-1-x86_64 +installed = lib32-fluidsynth-2.4.7-1-x86_64 +installed = lib32-fontconfig-2:2.17.1-1-x86_64 +installed = lib32-freetype2-2.13.3-3-x86_64 +installed = lib32-fribidi-1.0.16-2-x86_64 +installed = lib32-gamemode-1.8.2-1-x86_64 +installed = lib32-gcc-libs-15.1.1+r500+gb1b8d8ce3eea-1-x86_64 +installed = lib32-gdk-pixbuf2-2.42.12-2-x86_64 +installed = lib32-gettext-0.25-1-x86_64 +installed = lib32-giflib-5.2.2-1-x86_64 +installed = lib32-glib-networking-1:2.80.1-1-x86_64 +installed = lib32-glib2-2.84.3-1-x86_64 +installed = lib32-glibc-2.42+r3+gbc13db739377-1-x86_64 +installed = lib32-glu-9.0.3-2-x86_64 +installed = lib32-gmp-6.3.0-2-x86_64 +installed = lib32-gnutls-3.8.10-1-x86_64 +installed = lib32-gpm-1.20.7.r38.ge82d1a6-2-x86_64 +installed = lib32-gst-plugins-base-1.26.4-1-x86_64 +installed = lib32-gst-plugins-base-libs-1.26.4-1-x86_64 +installed = lib32-gst-plugins-good-1.26.4-1-x86_64 +installed = lib32-gstreamer-1.26.4-1-x86_64 +installed = lib32-gtk2-2.24.33-5-x86_64 +installed = lib32-harfbuzz-11.3.3-1-x86_64 +installed = lib32-icu-76.1-1-x86_64 +installed = lib32-imlib2-1.12.5-1-x86_64 +installed = lib32-json-c-0.18-2-x86_64 +installed = lib32-keyutils-1.6.3-2-x86_64 +installed = lib32-krb5-1.21.3-1-x86_64 +installed = lib32-libasyncns-1:0.8+r3+g68cd5af-3-x86_64 +installed = lib32-libavc1394-0.5.4-5-x86_64 +installed = lib32-libavtp-0.2.0-3-x86_64 +installed = lib32-libcaca-0.99.beta20-2-x86_64 +installed = lib32-libcap-2.76-1-x86_64 +installed = lib32-libcups-2.4.11-1-x86_64 +installed = lib32-libdatrie-0.2.13-3-x86_64 +installed = lib32-libdrm-2.4.125-1-x86_64 +installed = lib32-libdv-1.0.0-9-x86_64 +installed = lib32-libelf-0.193-1-x86_64 +installed = lib32-libffi-3.5.1-1-x86_64 +installed = lib32-libgcrypt-1.11.1-1-x86_64 +installed = lib32-libglvnd-1.7.0-1-x86_64 +installed = lib32-libgpg-error-1.55-1-x86_64 +installed = lib32-libgudev-238-3-x86_64 +installed = lib32-libidn2-2.3.7-1-x86_64 +installed = lib32-libiec61883-1.2.0-5-x86_64 +installed = lib32-libinstpatch-1.1.7-1-x86_64 +installed = lib32-libjpeg-turbo-3.1.1-1-x86_64 +installed = lib32-libldap-2.6.10-1-x86_64 +installed = lib32-libnghttp2-1.66.0-1-x86_64 +installed = lib32-libnghttp3-1.11.0-1-x86_64 +installed = lib32-libnl-3.11.0-1-x86_64 +installed = lib32-libnm-1.54.0-1-x86_64 +installed = lib32-libnsl-2.0.1-1-x86_64 +installed = lib32-libogg-1.3.6-1-x86_64 +installed = lib32-libpcap-1.10.5-3-x86_64 +installed = lib32-libpciaccess-0.18.1-1-x86_64 +installed = lib32-libpipewire-1:1.4.7-1-x86_64 +installed = lib32-libpng-1.6.50-1-x86_64 +installed = lib32-libproxy-0.5.10-1-x86_64 +installed = lib32-libpsl-0.21.5-1-x86_64 +installed = lib32-libpulse-17.0+r43+g3e2bb8a1e-1-x86_64 +installed = lib32-libraw1394-2.1.2-5-x86_64 +installed = lib32-librsvg-2:2.60.0-2-x86_64 +installed = lib32-libsamplerate-0.2.2-3-x86_64 +installed = lib32-libshout-1:2.4.6-4-x86_64 +installed = lib32-libsndfile-1.2.2-3-x86_64 +installed = lib32-libsoup3-3.6.5-1-x86_64 +installed = lib32-libssh2-1.11.1-1-x86_64 +installed = lib32-libtasn1-4.20.0-1-x86_64 +installed = lib32-libthai-0.1.29-3-x86_64 +installed = lib32-libtheora-1.2.0-1-x86_64 +installed = lib32-libtiff-4.7.0-1-x86_64 +installed = lib32-libtirpc-1.3.6-1-x86_64 +installed = lib32-libunistring-1.3-1-x86_64 +installed = lib32-libunwind-1.8.1-1-x86_64 +installed = lib32-libusb-1.0.29-1-x86_64 +installed = lib32-libva-2.22.0-1-x86_64 +installed = lib32-libvorbis-1.3.7-4-x86_64 +installed = lib32-libvpx-1.15.0-1-x86_64 +installed = lib32-libwebp-1.6.0-1-x86_64 +installed = lib32-libx11-1.8.12-2-x86_64 +installed = lib32-libxau-1.0.11-2-x86_64 +installed = lib32-libxcb-1.17.0-1-x86_64 +installed = lib32-libxcomposite-0.4.6-2-x86_64 +installed = lib32-libxcrypt-4.4.38-1-x86_64 +installed = lib32-libxcrypt-compat-4.4.38-1-x86_64 +installed = lib32-libxcursor-1.2.3-1-x86_64 +installed = lib32-libxdamage-1.1.6-2-x86_64 +installed = lib32-libxdmcp-1.1.5-1-x86_64 +installed = lib32-libxext-1.3.6-1-x86_64 +installed = lib32-libxfixes-6.0.1-2-x86_64 +installed = lib32-libxft-2.3.8-2-x86_64 +installed = lib32-libxi-1.8.2-1-x86_64 +installed = lib32-libxinerama-1.1.5-2-x86_64 +installed = lib32-libxkbcommon-1.10.0-1-x86_64 +installed = lib32-libxml2-2.14.5-1-x86_64 +installed = lib32-libxrandr-1.5.4-1-x86_64 +installed = lib32-libxrender-0.9.11-2-x86_64 +installed = lib32-libxshmfence-1.3.3-1-x86_64 +installed = lib32-libxss-1.2.4-2-x86_64 +installed = lib32-libxtst-1.2.5-2-x86_64 +installed = lib32-libxv-1.0.12-2-x86_64 +installed = lib32-libxxf86vm-1.1.5-2-x86_64 +installed = lib32-llvm-libs-1:20.1.8-1-x86_64 +installed = lib32-lm_sensors-1:3.6.2-2-x86_64 +installed = lib32-mesa-1:25.1.7-1-x86_64 +installed = lib32-mpg123-1.32.10-1-x86_64 +installed = lib32-ncurses-6.5-2-x86_64 +installed = lib32-nettle-3.10.2-1-x86_64 +installed = lib32-nspr-4.37-1-x86_64 +installed = lib32-nss-3.114-1-x86_64 +installed = lib32-nvidia-utils-575.64.05-1-x86_64 +installed = lib32-ocl-icd-2.3.3-1-x86_64 +installed = lib32-openal-1.24.3-1-x86_64 +installed = lib32-openssl-1:3.5.1-1-x86_64 +installed = lib32-opus-1.5.2-1-x86_64 +installed = lib32-orc-0.4.41-1-x86_64 +installed = lib32-p11-kit-0.25.5-1-x86_64 +installed = lib32-pam-1.7.0-1-x86_64 +installed = lib32-pango-1:1.56.4-1-x86_64 +installed = lib32-pcre2-10.45-1-x86_64 +installed = lib32-pcsclite-2.3.3-1-x86_64 +installed = lib32-pipewire-1:1.4.7-1-x86_64 +installed = lib32-pipewire-jack-1:1.4.7-1-x86_64 +installed = lib32-pixman-0.46.4-1-x86_64 +installed = lib32-polkit-126-1-x86_64 +installed = lib32-popt-1.19-2-x86_64 +installed = lib32-portaudio-1:19.7.0-3-x86_64 +installed = lib32-readline-8.2.013-1-x86_64 +installed = lib32-sdl2-compat-2.32.56-1-x86_64 +installed = lib32-sdl3-3.2.20-1-x86_64 +installed = lib32-simplescreenrecorder-git-0.4.4.r57.gc50e83e-1-x86_64 +installed = lib32-speex-1.2.1-2-x86_64 +installed = lib32-spirv-tools-1:1.4.321.0-1-x86_64 +installed = lib32-sqlite-3.50.2-1-x86_64 +installed = lib32-systemd-257.7-1-x86_64 +installed = lib32-taglib-2.0.2-1-x86_64 +installed = lib32-twolame-0.4.0-3-x86_64 +installed = lib32-util-linux-2.41.1-1-x86_64 +installed = lib32-v4l-utils-1.28.1-1-x86_64 +installed = lib32-vulkan-icd-loader-1.4.321.0-1-x86_64 +installed = lib32-wavpack-5.8.1-1-x86_64 +installed = lib32-wayland-1.23.1-1-x86_64 +installed = lib32-xz-5.8.1-1-x86_64 +installed = lib32-zlib-1.3.1-2-x86_64 +installed = lib32-zstd-1.5.7-2-x86_64 +installed = libabw-0.1.3-5-x86_64 +installed = libadwaita-1:1.7.6-1-x86_64 +installed = libaec-1.1.4-2-x86_64 +installed = libaemu-0.1.2-5-x86_64 +installed = libaio-0.3.113-3-x86_64 +installed = libao-1.2.2-7-x86_64 +installed = libappindicator-gtk3-12.10.0.r298-4-x86_64 +installed = libarchive-3.8.1-1-x86_64 +installed = libass-0.17.4-1-x86_64 +installed = libassuan-3.0.0-1-x86_64 +installed = libasyncns-1:0.8+r3+g68cd5af-3-x86_64 +installed = libatasmart-0.19-6-x86_64 +installed = libatomic_ops-7.8.2-1-x86_64 +installed = libavc1394-0.5.4-6-x86_64 +installed = libavif-1.3.0-1-x86_64 +installed = libavtp-0.2.0-3-x86_64 +installed = libb2-0.98.1-3-x86_64 +installed = libblockdev-3.3.1-1-x86_64 +installed = libblockdev-crypto-3.3.1-1-x86_64 +installed = libblockdev-fs-3.3.1-1-x86_64 +installed = libblockdev-loop-3.3.1-1-x86_64 +installed = libblockdev-mdraid-3.3.1-1-x86_64 +installed = libblockdev-nvme-3.3.1-1-x86_64 +installed = libblockdev-part-3.3.1-1-x86_64 +installed = libblockdev-swap-3.3.1-1-x86_64 +installed = libbluray-1.3.4-3-x86_64 +installed = libbpf-1.5.1-1-x86_64 +installed = libbs2b-3.1.0-9-x86_64 +installed = libbsd-0.12.2-2-x86_64 +installed = libburn-1.5.6-1-x86_64 +installed = libbytesize-2.11-1-x86_64 +installed = libcaca-0.99.beta20-5-x86_64 +installed = libcacard-2.8.1-1-x86_64 +installed = libcamera-0.5.1-2-x86_64 +installed = libcamera-ipa-0.5.1-2-x86_64 +installed = libcanberra-1:0.30+r2+gc0620e4-4-x86_64 +installed = libcap-2.76-1-x86_64 +installed = libcap-ng-0.8.5-3-x86_64 +installed = libcbor-0.12.0-1-x86_64 +installed = libcddb-1.3.2-7-x86_64 +installed = libcdio-2.2.0-1-x86_64 +installed = libcdio-paranoia-10.2+2.0.2-1-x86_64 +installed = libcdr-0.1.8-2-x86_64 +installed = libcloudproviders-0.3.6-2-x86_64 +installed = libcmis-0.6.2-5-x86_64 +installed = libcolord-1.4.8-1-x86_64 +installed = libcue-2.3.0-1-x86_64 +installed = libcups-2:2.4.12-2-x86_64 +installed = libcupsfilters-2.1.1-2-x86_64 +installed = libcurl-gnutls-8.15.0-1-x86_64 +installed = libdaemon-0.14-6-x86_64 +installed = libdatrie-0.2.13-4-x86_64 +installed = libdbusmenu-glib-16.04.0.r498-2-x86_64 +installed = libdbusmenu-gtk3-16.04.0.r498-2-x86_64 +installed = libdc1394-2.2.7-1-x86_64 +installed = libdca-0.0.7-2-x86_64 +installed = libde265-1.0.16-1-x86_64 +installed = libdecor-0.2.3-1-x86_64 +installed = libdeflate-1.24-1-x86_64 +installed = libdiscid-0.6.5-2-x86_64 +installed = libdisplay-info-0.2.0-2-x86_64 +installed = libdovi-3.3.2-1-x86_64 +installed = libdrm-2.4.125-1-x86_64 +installed = libdv-1.0.0-11-x86_64 +installed = libdvdcss-1.4.3-2-x86_64 +installed = libdvdnav-6.1.1-2-x86_64 +installed = libdvdread-6.1.3-2-x86_64 +installed = libe-book-0.1.3-18-x86_64 +installed = libebml-1.4.5-1-x86_64 +installed = libebur128-1.2.6-2-x86_64 +installed = libedit-20250104_3.1-1-x86_64 +installed = libei-1.4.1-1-x86_64 +installed = libelf-0.193-3-x86_64 +installed = libepoxy-1.5.10-3-x86_64 +installed = libepubgen-0.1.1-5-x86_64 +installed = libetonyek-0.1.12-3-x86_64 +installed = libev-4.33-4-x86_64 +installed = libevdev-1.13.4-1-x86_64 +installed = libevent-2.1.12-4-x86_64 +installed = libexif-0.6.25-1-x86_64 +installed = libexttextcat-3.4.7-1-x86_64 +installed = libfabric-2.2.0-1-x86_64 +installed = libfdk-aac-2.0.3-1-x86_64 +installed = libffi-3.5.1-1-x86_64 +installed = libfm-1.4.0-1-x86_64 +installed = libfm-extra-1.4.0-1-x86_64 +installed = libfm-gtk2-1.4.0-1-x86_64 +installed = libfontenc-1.1.8-1-x86_64 +installed = libfreeaptx-0.2.2-1-x86_64 +installed = libfreehand-0.1.2-5-x86_64 +installed = libftdi-1.5-7-x86_64 +installed = libgadu-1.12.2-14-x86_64 +installed = libgcrypt-1.11.1-1-x86_64 +installed = libgirepository-1.84.0-2-x86_64 +installed = libgit2-1:1.9.1-1-x86_64 +installed = libglvnd-1.7.0-3-x86_64 +installed = libgme-0.6.4-1-x86_64 +installed = libgovirt-2:0.3.9-2-x86_64 +installed = libgpg-error-1.55-1-x86_64 +installed = libgphoto2-2.5.32-2-x86_64 +installed = libgpod-0.8.3-17-x86_64 +installed = libgtop-2.41.3-2-x86_64 +installed = libgudev-238-3-x86_64 +installed = libgusb-0.4.9-2-x86_64 +installed = libheif-1.20.1-2-x86_64 +installed = libibus-1.5.32-1-x86_64 +installed = libice-1.1.2-1-x86_64 +installed = libid3tag-0.16.3-2-x86_64 +installed = libidn-1.43-1-x86_64 +installed = libidn2-2.3.7-1-x86_64 +installed = libiec61883-1.2.0-8-x86_64 +installed = libieee1284-0.2.11-18-x86_64 +installed = libimagequant-4.4.0-1-x86_64 +installed = libimobiledevice-1.3.0-17-x86_64 +installed = libimobiledevice-glue-1.3.2-1-x86_64 +installed = libinih-58-1-x86_64 +installed = libinput-1.28.1-1-x86_64 +installed = libinstpatch-1.1.7-2-x86_64 +installed = libisl-0.27-1-x86_64 +installed = libisoburn-1.5.6-1-x86_64 +installed = libisofs-1.5.6-1-x86_64 +installed = libixion-0.20.0-2-x86_64 +installed = libjcat-0.2.3-2-x86_64 +installed = libjpeg-turbo-3.1.1-1-x86_64 +installed = libjxl-0.11.1-4-x86_64 +installed = libkate-0.4.1-11-x86_64 +installed = libksba-1.6.7-2-x86_64 +installed = liblangtag-0.6.7-2-x86_64 +installed = liblc3-1.1.3-1-x86_64 +installed = libldac-2.0.2.3-2-x86_64 +installed = libldap-2.6.10-2-x86_64 +installed = liblo-1:0.32-1-x86_64 +installed = liblouis-3.34.0-1-x86_64 +installed = liblqr-0.4.3-1-x86_64 +installed = liblrdf-0.6.1-5-x86_64 +installed = libltc-1.3.2-2-x86_64 +installed = libluv-1.48.0_2-1-x86_64 +installed = liblzf-3.6-5-x86_64 +installed = libmad-0.15.1b-10-x86_64 +installed = libmanette-0.2.12-1-x86_64 +installed = libmatroska-1.7.1-2-x86_64 +installed = libmaxminddb-1.12.2-2-x86_64 +installed = libmbim-1.32.0-1-x86_64 +installed = libmd-1.1.0-2-x86_64 +installed = libmicrodns-0.2.0-2-x86_64 +installed = libmm-glib-1.24.2-1-x86_64 +installed = libmms-0.6.4-5-x86_64 +installed = libmng-2.0.3-4-x86_64 +installed = libmnl-1.0.5-2-x86_64 +installed = libmodplug-0.8.9.0-6-x86_64 +installed = libmp3splt-0.9.3.1519+r5+g4b48268-4-x86_64 +installed = libmp4v2-1:2.1.3-2-x86_64 +installed = libmpc-1.3.1-2-x86_64 +installed = libmpcdec-1:0.1+r475-6-x86_64 +installed = libmpeg2-0.5.1-11-x86_64 +installed = libmspack-1:1.11-1-x86_64 +installed = libmspub-0.1.4-17-x86_64 +installed = libmtp-1.1.22-1-x86_64 +installed = libmwaw-0.3.22-3-x86_64 +installed = libmysofa-1.3.3-1-x86_64 +installed = libnatpmp-20230423-3-x86_64 +installed = libnbd-1.22.3-1-x86_64 +installed = libndp-1.9-1-x86_64 +installed = libnet-2:1.3-1-x86_64 +installed = libnetfilter_conntrack-1.0.9-2-x86_64 +installed = libnewt-0.52.25-1-x86_64 +installed = libnfnetlink-1.0.2-2-x86_64 +installed = libnfs-6.0.2-5-x86_64 +installed = libnftnl-1.2.9-1-x86_64 +installed = libnghttp2-1.66.0-1-x86_64 +installed = libnghttp3-1.11.0-1-x86_64 +installed = libngtcp2-1.13.0-2-x86_64 +installed = libnice-0.1.22-2-x86_64 +installed = libnl-3.11.0-1-x86_64 +installed = libnm-1.54.0-1-x86_64 +installed = libnma-1.10.6-3-x86_64 +installed = libnma-common-1.10.6-3-x86_64 +installed = libnotify-0.8.6-1-x86_64 +installed = libnsl-2.0.1-1-x86_64 +installed = libnumbertext-1.0.11-2-x86_64 +installed = libnvme-1.15-1-x86_64 +installed = libodfgen-0.1.8-4-x86_64 +installed = libogg-1.3.6-1-x86_64 +installed = libopenmpt-0.8.2-1-x86_64 +installed = libopusenc-0.2.1-5-x86_64 +installed = liborcus-0.20.1-1-x86_64 +installed = libosinfo-1.12.0-2-x86_64 +installed = libotr-4.1.1-6-x86_64 +installed = libp11-kit-0.25.5-1-x86_64 +installed = libpagemaker-0.0.4-4-x86_64 +installed = libpaper-2.2.6-1-x86_64 +installed = libpcap-1.10.5-3-x86_64 +installed = libpciaccess-0.18.1-2-x86_64 +installed = libpeas-1.36.0-7-x86_64 +installed = libpeas-2-2.0.7-1-x86_64 +installed = libpgm-5.3.128-3-x86_64 +installed = libpipeline-1.5.8-1-x86_64 +installed = libpipewire-1:1.4.7-1-x86_64 +installed = libplacebo-7.351.0-2-x86_64 +installed = libplist-2.7.0-1-x86_64 +installed = libpng-1.6.50-1-x86_64 +installed = libportal-0.9.1-2-x86_64 +installed = libportal-gtk3-0.9.1-2-x86_64 +installed = libportal-gtk4-0.9.1-2-x86_64 +installed = libppd-2.1.1-1-x86_64 +installed = libproxy-0.5.10-1-x86_64 +installed = libpsl-0.21.5-2-x86_64 +installed = libpulse-17.0+r43+g3e2bb8a1e-1-x86_64 +installed = libpurple-2.14.14-3-x86_64 +installed = libpwquality-1.4.5-6-x86_64 +installed = libqmi-1.36.0-1-x86_64 +installed = libqrtr-glib-1.2.2-4-x86_64 +installed = libqxp-0.0.2-13-x86_64 +installed = libraqm-0.10.2-1-x86_64 +installed = libraw-0.21.4-1-x86_64 +installed = libraw1394-2.1.2-4-x86_64 +installed = libre-3.24.0-1-x86_64 +installed = libreoffice-still-24.8.7-4-x86_64 +installed = librest-0.9.1-3-x86_64 +installed = libretro-core-info-1.21.1-1-any +installed = librevenge-0.0.5-3-x86_64 +installed = librsvg-2:2.60.0-2-x86_64 +installed = libsamplerate-0.2.2-3-x86_64 +installed = libsasl-2.1.28-5-x86_64 +installed = libseccomp-2.5.6-1-x86_64 +installed = libsecp256k1-1:0.5.1-1-x86_64 +installed = libsecret-0.21.7-1-x86_64 +installed = libshout-1:2.4.6-5-x86_64 +installed = libsidplayfp-2.15.0-1-x86_64 +installed = libsigsegv-2.15-1-x86_64 +installed = libsixel-1.10.5-1-x86_64 +installed = libslirp-4.9.1-1-x86_64 +installed = libsm-1.2.6-1-x86_64 +installed = libsndfile-1.2.2-3-x86_64 +installed = libsodium-1.0.20-1-x86_64 +installed = libsonic-0.2.0-2-x86_64 +installed = libsoup3-3.6.5-1-x86_64 +installed = libsoxr-0.1.3-4-x86_64 +installed = libspectre-0.2.12-2-x86_64 +installed = libspeechd-0.12.1-1-x86_64 +installed = libsrtp-1:2.7.0-1-x86_64 +installed = libssh-0.11.2-1-x86_64 +installed = libssh2-1.11.1-1-x86_64 +installed = libstaroffice-0.0.7-4-x86_64 +installed = libstemmer-3.0.1-1-x86_64 +installed = libsynctex-2025.2-1-x86_64 +installed = libsysprof-capture-48.0-6-x86_64 +installed = libtasn1-4.20.0-1-x86_64 +installed = libteam-1.32-2-x86_64 +installed = libthai-0.1.29-3-x86_64 +installed = libtheora-1.2.0-1-x86_64 +installed = libtiff-4.7.0-1-x86_64 +installed = libtirpc-1.3.6-2-x86_64 +installed = libtommath-1.3.0-1-x86_64 +installed = libtool-2.5.4+r23+g5b582aed-2-x86_64 +installed = libtpms-0.10.1-1-x86_64 +installed = libtraceevent-1:1.8.4-1-x86_64 +installed = libtracefs-1.8.2-1-x86_64 +installed = libunibreak-6.1-1-x86_64 +installed = libunistring-1.3-1-x86_64 +installed = libunrar-1:7.1.10-1-x86_64 +installed = libunwind-1.8.2-1-x86_64 +installed = libupnp-1.14.24-1-x86_64 +installed = liburcu-0.15.3-1-x86_64 +installed = liburing-2.11-1-x86_64 +installed = libusb-1.0.29-1-x86_64 +installed = libusb-compat-0.1.8-2-x86_64 +installed = libusbmuxd-2.1.1-1-x86_64 +installed = libutempter-1.2.3-1-x86_64 +installed = libutf8proc-2.10.0-1-x86_64 +installed = libuv-1.51.0-1-x86_64 +installed = libva-2.22.0-1-x86_64 +installed = libvdpau-1.5-3-x86_64 +installed = libverto-0.3.2-5-x86_64 +installed = libvirt-1:11.6.0-1-x86_64 +installed = libvirt-glib-5.0.0-3-x86_64 +installed = libvirt-python-1:11.6.0-1-x86_64 +installed = libvisio-0.1.8-3-x86_64 +installed = libvlc-3.0.21-27-x86_64 +installed = libvorbis-1.3.7-4-x86_64 +installed = libvpl-2.15.0-1-x86_64 +installed = libvpx-1.15.0-1-x86_64 +installed = libvterm-0.3.3-2-x86_64 +installed = libwacom-2.16.1-1-x86_64 +installed = libwbclient-2:4.22.3-1-x86_64 +installed = libwebp-1.6.0-1-x86_64 +installed = libwireplumber-0.5.10-1-x86_64 +installed = libwmf-0.2.13-4-x86_64 +installed = libwnck3-43.2-1-x86_64 +installed = libwpd-0.10.3-5-x86_64 +installed = libwpg-0.3.4-2-x86_64 +installed = libwps-0.4.14-3-x86_64 +installed = libx11-1.8.12-1-x86_64 +installed = libxau-1.0.12-1-x86_64 +installed = libxaw-1.0.16-1-x86_64 +installed = libxcb-1.17.0-1-x86_64 +installed = libxcomposite-0.4.6-2-x86_64 +installed = libxcrypt-4.4.38-1-x86_64 +installed = libxcrypt-compat-4.4.38-1-x86_64 +installed = libxcursor-1.2.3-1-x86_64 +installed = libxcvt-0.1.3-1-x86_64 +installed = libxdamage-1.1.6-2-x86_64 +installed = libxdmcp-1.1.5-1-x86_64 +installed = libxdp-1.5.5-1-x86_64 +installed = libxext-1.3.6-1-x86_64 +installed = libxfce4ui-4.20.1-2-x86_64 +installed = libxfce4util-4.20.1-1-x86_64 +installed = libxfixes-6.0.1-2-x86_64 +installed = libxfont2-2.0.7-1-x86_64 +installed = libxft-2.3.9-1-x86_64 +installed = libxi-1.8.2-1-x86_64 +installed = libxinerama-1.1.5-2-x86_64 +installed = libxkbcommon-1.10.0-1-x86_64 +installed = libxkbcommon-x11-1.10.0-1-x86_64 +installed = libxkbfile-1.1.3-1-x86_64 +installed = libxklavier-5.4-6-x86_64 +installed = libxml2-2.14.5-1-x86_64 +installed = libxmlb-0.3.22-1-x86_64 +installed = libxmp-4.6.3-1-x86_64 +installed = libxmu-1.2.1-1-x86_64 +installed = libxpm-3.5.17-2-x86_64 +installed = libxpresent-1.0.1-2-x86_64 +installed = libxrandr-1.5.4-1-x86_64 +installed = libxrender-0.9.12-1-x86_64 +installed = libxres-1.2.2-2-x86_64 +installed = libxshmfence-1.3.3-1-x86_64 +installed = libxslt-1.1.43-2-x86_64 +installed = libxss-1.2.4-2-x86_64 +installed = libxt-1.3.1-1-x86_64 +installed = libxtst-1.2.5-1-x86_64 +installed = libxv-1.0.13-1-x86_64 +installed = libxxf86vm-1.1.6-1-x86_64 +installed = libyaml-0.2.5-3-x86_64 +installed = libyuv-r2426+464c51a03-1-x86_64 +installed = libzip-1.11.4-1-x86_64 +installed = libzmf-0.0.2-17-x86_64 +installed = licenses-20240728-1-any +installed = lilv-0.24.26-1-x86_64 +installed = linux-6.15.9.arch1-1-x86_64 +installed = linux-api-headers-6.16-1-x86_64 +installed = linux-firmware-20250708-1-any +installed = linux-firmware-amdgpu-20250708-1-any +installed = linux-firmware-atheros-20250708-1-any +installed = linux-firmware-broadcom-20250708-1-any +installed = linux-firmware-cirrus-20250708-1-any +installed = linux-firmware-intel-20250708-1-any +installed = linux-firmware-mediatek-20250708-1-any +installed = linux-firmware-nvidia-20250708-1-any +installed = linux-firmware-other-20250708-1-any +installed = linux-firmware-radeon-20250708-1-any +installed = linux-firmware-realtek-20250708-1-any +installed = linux-firmware-whence-20250708-1-any +installed = linux-headers-6.15.9.arch1-1-x86_64 +installed = lirc-1:0.10.2-5-x86_64 +installed = llhttp-9.2.1-2-x86_64 +installed = lltag-0.14.6-1-x86_64 +installed = llvm-20.1.8-1-x86_64 +installed = llvm-libs-20.1.8-1-x86_64 +installed = lm_sensors-1:3.6.2-1-x86_64 +installed = lmdb-0.9.33-1-x86_64 +installed = love-11.5-2-x86_64 +installed = lpsolve-5.5.2.11-3-x86_64 +installed = lsb-release-2.0.r55.a25a4fc-1-any +installed = lshw-B.02.20-1-x86_64 +installed = lsof-4.99.5-2-x86_64 +installed = lua-5.4.8-2-x86_64 +installed = lua-bit32-1:0.14-1-x86_64 +installed = lua-posix-36.3-1-x86_64 +installed = lua-socket-1:3.1.0-1-x86_64 +installed = lua51-5.1.5-13-x86_64 +installed = lua51-lpeg-1.1.0-3-x86_64 +installed = luajit-2.1.1753364724-1-x86_64 +installed = luarocks-3.12.2-1-any +installed = lv2-1.18.10-1-x86_64 +installed = lxmenu-data-0.1.6-1-any +installed = lxsession-1:0.5.6-1-x86_64 +installed = lxterminal-0.4.1-1-x86_64 +installed = lz4-1:1.10.0-2-x86_64 +installed = lzo-2.10-5-x86_64 +installed = m4-1.4.20-1-x86_64 +installed = magic-wormhole-0.20.0-1-any +installed = mailcap-2.1.54-2-any +installed = make-4.4.1-2-x86_64 +installed = man-db-2.13.1-1-x86_64 +installed = mariadb-libs-11.8.2-1-x86_64 +installed = mate-desktop-1.28.2-2-x86_64 +installed = mathjax-3.2.2-2-any +installed = maven-3.9.10-1-any +installed = maxcso-1.13.0-3-x86_64 +installed = md4c-0.5.2-1-x86_64 +installed = mdadm-4.4-1-x86_64 +installed = mednafen-1.32.1-2-x86_64 +installed = mednafen-server-0.5.2-1-x86_64 +installed = mednaffe-0.9.3-2-x86_64 +installed = menu-cache-1.1.1-1-x86_64 +installed = mesa-1:25.1.7-1-x86_64 +installed = mesa-utils-9.0.0-7-x86_64 +installed = meson-1.8.3-1-any +installed = mingw-w64-binutils-2.44-2-x86_64 +installed = mingw-w64-crt-13.0.0-1-any +installed = mingw-w64-gcc-15.1.0-2-x86_64 +installed = mingw-w64-headers-13.0.0-1-any +installed = mingw-w64-wine-1-11-any +installed = mingw-w64-winpthreads-13.0.0-1-any +installed = miniupnpc-2.3.3-1-x86_64 +installed = minizip-1:1.3.1-2-x86_64 +installed = mjpegtools-2.2.1-3-x86_64 +installed = mkchromecast-git-0.3.8.1.r309.g28a0ea89-1-any +installed = mkinitcpio-39.2-3-any +installed = mkinitcpio-busybox-1.36.1-1-x86_64 +installed = mobile-broadband-provider-info-20250613-1-any +installed = mp3splt-2.6.3.1519+r2+g4b48268-3-x86_64 +installed = mpdecimal-4.0.1-1-x86_64 +installed = mpfr-4.2.2-1-x86_64 +installed = mpg123-1.33.1-1-x86_64 +installed = mpv-1:0.40.0-5-x86_64 +installed = mpv-mpris-1.1-3-x86_64 +installed = msgpack-c-6.1.0-2-x86_64 +installed = mtdev-1.1.7-1-x86_64 +installed = mtools-1:4.0.49-1-x86_64 +installed = mujs-1.3.7-1-x86_64 +installed = mumble-1.5.735-12-x86_64 +installed = mutt-2.2.14-2-x86_64 +installed = mypy-1.17.0-1-any +installed = nano-8.5-1-x86_64 +installed = ncspot-bin-1.3.0-1-x86_64 +installed = ncurses-6.5-4-x86_64 +installed = ndctl-79-1-x86_64 +installed = needrestart-3.11-1-any +installed = neon-0.35.0-1-x86_64 +installed = neovim-0.11.3-1-x86_64 +installed = net-snmp-5.9.4-7-x86_64 +installed = net-tools-2.10-3-x86_64 +installed = netpbm-10.86.47-1-x86_64 +installed = nettle-3.10.2-1-x86_64 +installed = networkmanager-1.54.0-1-x86_64 +installed = nftables-1:1.1.3-1-x86_64 +installed = ninja-1.12.1-2-x86_64 +installed = ninjam-client-r4194.dd7cf64c-1-x86_64 +installed = nm-connection-editor-1.36.0-1-x86_64 +installed = nmap-7.97-1-x86_64 +installed = node-gyp-11.3.0-1-any +installed = nodejs-24.5.0-1-x86_64 +installed = nodejs-nopt-7.2.1-1-any +installed = nodm-dgw-0.13-2-x86_64 +installed = normalize-0.7.7-7-x86_64 +installed = notestorm-git-r21.cbe8300-1-any +installed = notification-daemon-3.20.0-6-x86_64 +installed = npm-11.5.2-1-any +installed = npth-1.8-1-x86_64 +installed = nspr-4.37-1-x86_64 +installed = nss-3.114-1-x86_64 +installed = numactl-2.0.19-1-x86_64 +installed = nvidia-open-575.64.05-4-x86_64 +installed = nvidia-utils-575.64.05-2-x86_64 +installed = nvim-lazy-1:v11.17.1-1-any +installed = ocaml-5.3.0-1-x86_64 +installed = ocl-icd-2.3.3-1-x86_64 +installed = ocrdesktop-git-4.0.r3.gd99b0c6-1-any +installed = ollama-0.11.2-1-x86_64 +installed = ollama-cuda-0.11.2-1-x86_64 +installed = onetbb-2022.2.0-1-x86_64 +installed = oniguruma-6.9.10-1-x86_64 +installed = openai-codex-0.10.0-1-x86_64 +installed = openal-1.24.3-1-x86_64 +installed = opencl-headers-2:2024.10.24-1-any +installed = opencl-nvidia-575.64.05-2-x86_64 +installed = opencore-amr-0.1.6-2-x86_64 +installed = opencv-4.12.0-2-x86_64 +installed = opendht-1:3.2.0-2-x86_64 +installed = openexr-3.3.5-1-x86_64 +installed = openh264-2.6.0-1-x86_64 +installed = openjpeg2-2.5.3-1-x86_64 +installed = openmpi-5.0.8-1-x86_64 +installed = openpmix-5.0.8-1-x86_64 +installed = openresolv-3.17.0-1-any +installed = openssh-10.0p1-4-x86_64 +installed = openssl-3.5.1-1-x86_64 +installed = openucx-1.18.1-4-x86_64 +installed = openxr-1.1.50-1-x86_64 +installed = optipng-7.9.1-1-x86_64 +installed = opus-1.5.2-1-x86_64 +installed = opus-tools-0.2-7-x86_64 +installed = opusfile-0.12-4-x86_64 +installed = opustags-1.10.1-1-x86_64 +installed = orc-0.4.41-1-x86_64 +installed = orca-git-49.alpha.r72.g128f5d6c2-1-any +installed = osinfo-db-20250606-1-any +installed = p11-kit-0.25.5-1-x86_64 +installed = pacman-7.0.0.r6.gc685ae6-6-x86_64 +installed = pacman-contrib-1.12.0-1-x86_64 +installed = pacman-mirrorlist-20250702-2-any +installed = pahole-1:1.30-2-x86_64 +installed = pam-1.7.1-1-x86_64 +installed = pambase-20250719-1-any +installed = pamixer-1.6-3-x86_64 +installed = pandoc-bin-3.7.0.2-1-x86_64 +installed = pango-1:1.56.4-1-x86_64 +installed = parted-3.6-2-x86_64 +installed = passim-0.1.10-1-x86_64 +installed = patch-2.8-1-x86_64 +installed = pavucontrol-qt-2.2.0-1-x86_64 +installed = pcaudiolib-1.3-1-x86_64 +installed = pciutils-3.14.0-1-x86_64 +installed = pcmanfm-1.4.0-1-x86_64 +installed = pcre-8.45-4-x86_64 +installed = pcre2-10.45-1-x86_64 +installed = pcsclite-2.3.3-1-x86_64 +installed = pdmenu-1.3.6-1-x86_64 +installed = peertube-viewer-rs-1.8.7-1-any +installed = perl-5.42.0-1-x86_64 +installed = perl-alien-build-2.84-3-any +installed = perl-alien-libxml2-0.20-3-any +installed = perl-archive-zip-1.68-11-any +installed = perl-cairo-gobject-1.005-5-x86_64 +installed = perl-capture-tiny-0.50-3-any +installed = perl-class-inspector-1.36-9-any +installed = perl-class-method-modifiers-2.15-5-any +installed = perl-clone-0.47-2-x86_64 +installed = perl-common-sense-3.75-9-any +installed = perl-config-tiny-2.30-1-any +installed = perl-convert-binhex-1.125-15-any +installed = perl-curses-1.45-3-x86_64 +installed = perl-curses-ui-0.9609-13-any +installed = perl-data-dump-1.25-7-any +installed = perl-data-optlist-0.114-5-any +installed = perl-dbd-sqlite-1.76-2-x86_64 +installed = perl-dbi-1.647-2-x86_64 +installed = perl-devel-globaldestruction-0.14-12-any +installed = perl-encode-locale-1.05-14-any +installed = perl-error-0.17030-2-any +installed = perl-ffi-checklib-0.31-7-any +installed = perl-file-chdir-0.1011-6-any +installed = perl-file-homedir-1.006-7-any +installed = perl-file-listing-6.16-5-any +installed = perl-file-sharedir-1.118-7-any +installed = perl-file-which-1.27-7-any +installed = perl-glib-object-introspection-0.051-3-x86_64 +installed = perl-gtk3-0.038-5-any +installed = perl-html-parser-3.83-2-x86_64 +installed = perl-html-tagset-3.24-3-any +installed = perl-http-cookiejar-0.014-4-any +installed = perl-http-cookies-6.11-3-any +installed = perl-http-daemon-6.16-5-any +installed = perl-http-date-6.06-4-any +installed = perl-http-message-7.00-2-any +installed = perl-http-negotiate-6.01-15-any +installed = perl-import-into-1.002005-12-any +installed = perl-io-html-1.004-7-any +installed = perl-io-socket-ssl-2.094-2-any +installed = perl-io-stringy-2.113-2-any +installed = perl-json-4.10-2-any +installed = perl-json-xs-4.03-7-x86_64 +installed = perl-libintl-perl-1.35-2-x86_64 +installed = perl-libwww-6.79-2-any +installed = perl-lwp-mediatypes-6.04-7-any +installed = perl-lwp-protocol-https-6.14-3-any +installed = perl-lwp-useragent-cached-0.08-4-any +installed = perl-mailtools-2.22-2-any +installed = perl-mime-charset-1.013.1-5-any +installed = perl-mime-tools-5.515-3-any +installed = perl-module-find-0.17-2-any +installed = perl-module-runtime-0.018-1-any +installed = perl-module-scandeps-1.37-2-any +installed = perl-moo-2.005005-5-any +installed = perl-mp3-tag-1.16-1-any +installed = perl-net-http-6.23-5-any +installed = perl-net-ssleay-1.94-3-x86_64 +installed = perl-parallel-forkmanager-2.03-3-any +installed = perl-params-util-1.102-7-x86_64 +installed = perl-path-tiny-0.150-1-any +installed = perl-proc-processtable-0.636-4-x86_64 +installed = perl-role-tiny-2.002004-7-any +installed = perl-sort-naturally-1.03-12-any +installed = perl-sub-exporter-0.991-3-any +installed = perl-sub-exporter-progressive-0.001013-12-any +installed = perl-sub-install-0.929-3-any +installed = perl-sub-quote-1:2.006008-5-any +installed = perl-term-readkey-2.38-11-x86_64 +installed = perl-term-readline-gnu-1.47-2-x86_64 +installed = perl-test-pod-1.52-11-any +installed = perl-timedate-2.33-8-any +installed = perl-try-tiny-0.32-3-any +installed = perl-types-serialiser-1.01-5-any +installed = perl-unicode-linebreak-2019.001-9-x86_64 +installed = perl-uri-5.32-2-any +installed = perl-uri-find-20160806-1-any +installed = perl-www-robotrules-6.02-15-any +installed = perl-xml-libxml-2.0210-4-x86_64 +installed = perl-xml-namespacesupport-1.12-6-any +installed = perl-xml-parser-2.47-3-x86_64 +installed = perl-xml-sax-1.02-2-any +installed = perl-xml-sax-base-1.09-6-any +installed = perl-xml-sax-expat-0.51-8-any +installed = perl-xml-simple-2.25-11-any +installed = perl-yaml-tiny-1.76-2-any +installed = phodav-3.0-4-x86_64 +installed = phonon-qt5-4.12.0-8-x86_64 +installed = physfs-3.2.0-4-x86_64 +installed = pianobar-git-848.e1b593b-1-x86_64 +installed = pidgin-2.14.14-3-x86_64 +installed = pinentry-1.3.1-5-x86_64 +installed = pipe-viewer-git-0.5.6.r17.g5229c24-1-any +installed = piper-tts-bin-2023.11.14-1-x86_64 +installed = piper-voices-common-1.0.0-5-any +installed = piper-voices-en-us-1.0.0-3-any +installed = pipewire-1:1.4.7-1-x86_64 +installed = pipewire-alsa-1:1.4.7-1-x86_64 +installed = pipewire-audio-1:1.4.7-1-x86_64 +installed = pipewire-jack-1:1.4.7-1-x86_64 +installed = pipewire-pulse-1:1.4.7-1-x86_64 +installed = pixman-0.46.4-1-x86_64 +installed = pkgconf-2.5.1-1-x86_64 +installed = pkgstats-3.3.3-1-x86_64 +installed = playerctl-2.4.1-4-x86_64 +installed = pluma-1.28.0-6-x86_64 +installed = pmount-0.9.23-17-x86_64 +installed = po4a-0.73-1-any +installed = poco-1.14.2-1-x86_64 +installed = podget-1.0.0-1-any +installed = podofo-0.10.4-2-x86_64 +installed = polkit-126-2-x86_64 +installed = poppler-25.07.0-1-x86_64 +installed = poppler-data-0.4.12-2-any +installed = poppler-glib-25.07.0-1-x86_64 +installed = popt-1.19-2-x86_64 +installed = portaudio-1:19.7.0-3-x86_64 +installed = portmidi-1:2.0.6-1-x86_64 +installed = portsmf-234-3-x86_64 +installed = potrace-1.16-3-x86_64 +installed = ppsspp-1.19.3-1-x86_64 +installed = ppsspp-assets-1.19.3-1-x86_64 +installed = procps-ng-4.0.5-3-x86_64 +installed = project-brutality-git-3.0.0.alpha.4910.gfbd5534ab-1-any +installed = protobuf-31.1-2-x86_64 +installed = protobuf-c-1.5.2-4-x86_64 +installed = prrte-3.0.11-1-x86_64 +installed = psmisc-23.7-1-x86_64 +installed = pugixml-1.15-2-x86_64 +installed = pybind11-3.0.0-1-any +installed = pyenv-1:2.6.5-1-any +installed = pyenv-virtualenv-1:1.2.4-1-any +installed = pyinstaller-6.15.0-1-x86_64 +installed = pyinstaller-hooks-contrib-2025.8-1-any +installed = pyside6-6.9.1-2-x86_64 +installed = python-3.13.5-1-x86_64 +installed = python-absl-2.3.1-1-any +installed = python-accessible-output2-0.17-1-any +installed = python-aiohappyeyeballs-2.6.1-1-any +installed = python-aiohttp-3.12.15-1-x86_64 +installed = python-aiosignal-1.4.0-1-any +installed = python-alembic-1.16.1-1-any +installed = python-altgraph-0.17.4-1-any +installed = python-annotated-types-0.7.0-2-any +installed = python-ansimarkup-2.1.0-1-any +installed = python-anyio-4.10.0-1-any +installed = python-appdirs-1.4.4-11-any +installed = python-apsw-3.49.2.0-1-x86_64 +installed = python-argcomplete-3.6.2-1-any +installed = python-astor-0.8.1-8-any +installed = python-asttokens-3.0.0-1-any +installed = python-astunparse-1.6.3-9-any +installed = python-asyncssh-2.21.0-1-any +installed = python-atspi-2.46.1-3-any +installed = python-attrs-25.3.0-1-any +installed = python-audioop-lts-0.2.1-2-x86_64 +installed = python-autobahn-24.4.2-3-x86_64 +installed = python-autocommand-2.2.2-7-any +installed = python-automat-22.10.0-7-any +installed = python-babel-2.17.0-1-any +installed = python-bcrypt-4.3.0-1-x86_64 +installed = python-beautifulsoup4-4.13.3-1-any +installed = python-black-25.1.0-1-any +installed = python-bleach-6.2.0-2-any +installed = python-blinker-1.8.2-2-any +installed = python-boto3-1.39.9-1-any +installed = python-botocore-1.39.9-1-any +installed = python-bottle-0.13.2-1-any +installed = python-brotli-1.1.0-3-x86_64 +installed = python-brotlicffi-1.1.0.0-3-x86_64 +installed = python-build-1.3.0-1-any +installed = python-cachecontrol-1:0.14.3-1-any +installed = python-cachetools-5.5.0-2-any +installed = python-cachy-0.3.0-11-any +installed = python-cairo-1.28.0-1-x86_64 +installed = python-casttube-0.2.1-4-any +installed = python-certifi-2025.08.03-1-any +installed = python-cffi-1.17.1-2-x86_64 +installed = python-chardet-5.2.0-6-any +installed = python-charset-normalizer-3.4.2-1-any +installed = python-cleo-1:2.1.0-1-any +installed = python-click-8.2.1-1-any +installed = python-colorama-0.4.6-5-any +installed = python-comm-0.2.3-1-any +installed = python-constantly-23.10.4-2-any +installed = python-contourpy-1.3.3-1-x86_64 +installed = python-crashtest-0.4.1-4-any +installed = python-cryptography-45.0.5-1-x86_64 +installed = python-css-parser-1.0.10-3-any +installed = python-cssselect-1.2.0-8-any +installed = python-cycler-0.12.1-3-any +installed = python-daemonize-2.5.0-8-any +installed = python-dasbus-1.7-4-any +installed = python-dateutil-2.9.0-6-any +installed = python-dbus-1.4.0-1-x86_64 +installed = python-decorator-5.2.1-1-any +installed = python-defusedxml-0.7.1-7-any +installed = python-deprecated-1.2.18-1-any +installed = python-distlib-0.3.9-2-any +installed = python-distro-1.9.0-3-any +installed = python-dlib-20.0-1-x86_64 +installed = python-dnspython-1:2.7.0-1-any +installed = python-docutils-1:0.21.2-3-any +installed = python-dulwich-0.24.1-1-x86_64 +installed = python-ecdsa-0.19.1-1-any +installed = python-email-validator-2.2.0-2-any +installed = python-emoji-2.14.1-1-any +installed = python-entrypoints-0.4-6-any +installed = python-espeak-ng-0.1.8-1-any +installed = python-evdev-1.9.2-1-x86_64 +installed = python-executing-2.2.0-1-any +installed = python-fastjsonschema-2.21.1-1-any +installed = python-faust-cchardet-2.1.19-4-x86_64 +installed = python-feedparser-6.0.11-3-any +installed = python-ffmpy-0.6.1-1-any +installed = python-fido2-2.0.0-1-any +installed = python-filelock-3.18.0-1-any +installed = python-findpython-0.7.0-1-any +installed = python-flake8-1:7.2.0-2-any +installed = python-flake8-isort-6.1.1-4-any +installed = python-flask-3.1.1-1-any +installed = python-flatbuffers-25.2.10-1-x86_64 +installed = python-fonttools-4.59.0-1-x86_64 +installed = python-frontmatter-1.1.0-1-any +installed = python-frozenlist-1.7.0-1-x86_64 +installed = python-gast-0.6.0-2-any +installed = python-geoip-1.3.2-17-x86_64 +installed = python-gobject-3.52.3-3-x86_64 +installed = python-google-auth-2.40.3-1-any +installed = python-google-auth-oauthlib-1.2.1-2-any +installed = python-greenlet-3.2.1-1-x86_64 +installed = python-grpcio-1.74.0-1-x86_64 +installed = python-grpcio-tools-1.74.0-1-x86_64 +installed = python-h11-0.16.0-1-any +installed = python-h2-4.2.0-1-any +installed = python-h5py-3.14.0-1-x86_64 +installed = python-hkdf-0.0.3-14-any +installed = python-hpack-4.1.0-1-any +installed = python-html2text-2025.4.15-1-any +installed = python-html5-parser-0.4.12-4-x86_64 +installed = python-html5lib-1.1-15-any +installed = python-httpcore-1.0.9-2-any +installed = python-httplib2-0.22.0-8-any +installed = python-httpx-0.28.1-3-any +installed = python-humanize-4.12.3-1-any +installed = python-hyperframe-6.1.0-1-any +installed = python-hyperlink-21.0.0-7-any +installed = python-hypothesis-6.136.2-1-any +installed = python-i3ipc-2.2.1-8-any +installed = python-icalendar-6.3.1-1-any +installed = python-idna-3.10-2-any +installed = python-ifaddr-0.2.0-6-any +installed = python-importlib-metadata-8.7.0-1-any +installed = python-incremental-22.10.0-7-any +installed = python-inflate64-1.0.3-1-x86_64 +installed = python-inflect-7.5.0-1-any +installed = python-iniconfig-2.1.0-1-any +installed = python-installer-0.7.0-10-any +installed = python-intelhex-2.3.0-8-any +installed = python-ipykernel-6.30.0-1-any +installed = python-ipython-pygments-lexers-1.1.1-1-any +installed = python-isort-6.0.1-1-any +installed = python-iterable-io-1.0.0-4-any +installed = python-itsdangerous-2.2.0-1-any +installed = python-jaconv-0.4.0-1-any +installed = python-jaraco.classes-3.4.0-2-any +installed = python-jaraco.collections-5.1.0-1-any +installed = python-jaraco.context-6.0.1-1-any +installed = python-jaraco.functools-4.1.0-1-any +installed = python-jaraco.text-4.0.0-2-any +installed = python-jedi-0.19.2-1-any +installed = python-jeepney-0.9.0-1-any +installed = python-jinja-1:3.1.6-1-any +installed = python-jiter-0.10.0-1-x86_64 +installed = python-jmespath-1.0.1-5-any +installed = python-jsonschema-4.25.0-1-any +installed = python-jsonschema-specifications-2025.4.1-1-any +installed = python-jupyter-client-8.6.3-3-any +installed = python-jupyter-core-5.8.1-1-any +installed = python-keras-3.11.0-1-any +installed = python-keyring-25.6.0-1-any +installed = python-kiwisolver-1.4.7-1-x86_64 +installed = python-lark-parser-1.2.2-3-any +installed = python-libloader-1.3.1-1-any +installed = python-librespot-0.0.9-1-x86_64 +installed = python-lockfile-0.12.2-14-any +installed = python-lxml-6.0.0-2-x86_64 +installed = python-lxml-html-clean-0.4.2-1-any +installed = python-magic-1:0.4.27-5-any +installed = python-mako-1.3.10-1-any +installed = python-markdown-3.8.2-1-any +installed = python-markdown-it-py-3.0.0-4-any +installed = python-markupsafe-3.0.2-1-x86_64 +installed = python-matplotlib-3.10.5-1-x86_64 +installed = python-matplotlib-inline-0.1.7-2-any +installed = python-mccabe-0.7.0-8-any +installed = python-mdurl-0.1.2-8-any +installed = python-mechanize-1:0.4.10-2-any +installed = python-ml-dtypes-0.5.2-1-x86_64 +installed = python-more-itertools-10.7.0-1-any +installed = python-mouseinfo-0.1.3-1-any +installed = python-msgpack-1.0.5-3-x86_64 +installed = python-mss-10.0.0-2-any +installed = python-multidict-6.6.3-1-x86_64 +installed = python-multivolumefile-0.2.3-9-any +installed = python-music-tag-0.4.3-1-x86_64 +installed = python-mutagen-1.47.0-3-any +installed = python-mygpoclient-1.9-4-any +installed = python-mypy_extensions-1.0.0-5-any +installed = python-nest-asyncio-1.6.0-4-any +installed = python-netifaces-0.11.0-7-x86_64 +installed = python-numexpr-2.10.2-1-x86_64 +installed = python-numpy-2.3.2-1-x86_64 +installed = python-oauth2client-4.1.3-11-any +installed = python-oauthlib-3.3.1-1-any +installed = python-ollama-0.4.7-1-any +installed = python-openai-1.97.1-1-any +installed = python-opencv-4.12.0-2-x86_64 +installed = python-opt_einsum-3.4.0-1-any +installed = python-optree-0.13.1-2-any +installed = python-orjson-3.11.1-1-x86_64 +installed = python-packaging-25.0-1-any +installed = python-pandas-2.3.1-1-x86_64 +installed = python-paramiko-3.5.1-1-any +installed = python-parso-1:0.8.4-3-any +installed = python-pasta-0.2.0-9-any +installed = python-pathspec-0.12.1-3-any +installed = python-pbs-installer-2025.07.23-1-any +installed = python-pdfminer-20240706-2-any +installed = python-pdftotext-2.2.2-9-x86_64 +installed = python-pexpect-4.9.0-4-any +installed = python-pillow-11.3.0-1-x86_64 +installed = python-pip-25.2-1-any +installed = python-pipx-1.7.1-2-any +installed = python-pkginfo-1.12.0-1-any +installed = python-platform-utils-1.5.4-1-any +installed = python-platformdirs-4.3.6-2-any +installed = python-playsound-1.3.0-2-any +installed = python-playwright-1.54.0-1-any +installed = python-pluggy-1.6.0-1-any +installed = python-plyer-2.1.0-1-any +installed = python-pocketsphinx-5.0.4-1-x86_64 +installed = python-podcastparser-0.6.10-6-any +installed = python-poetry-2.1.2-1-any +installed = python-poetry-core-2.1.3-1-any +installed = python-poetry-plugin-export-1.9.0-1-any +installed = python-pooch-1.8.2-4-any +installed = python-prettytable-3.16.0-1-any +installed = python-prompt-toolkit-3.0.51-1-any +installed = python-prompt_toolkit-3.0.51-1-any +installed = python-propcache-0.3.2-1-x86_64 +installed = python-protobuf-31.1-2-x86_64 +installed = python-psutil-7.0.0-1-x86_64 +installed = python-ptyprocess-0.7.0-8-any +installed = python-pure-eval-0.2.3-2-any +installed = python-py7zr-1.0.0-1-any +installed = python-pyasn1-0.6.0-2-any +installed = python-pyasn1-modules-0.4.0-2-any +installed = python-pyaudio-0.2.14-4-x86_64 +installed = python-pyautogui-0.9.54-2-any +installed = python-pybcj-1.0.6-1-x86_64 +installed = python-pychm-0.8.6-9-x86_64 +installed = python-pychromecast-14.0.7-3-any +installed = python-pycodestyle-2.14.0-1-any +installed = python-pycparser-2.22-3-any +installed = python-pycryptodome-3.23.0-1-x86_64 +installed = python-pycryptodomex-3.23.0-1-x86_64 +installed = python-pycups-2.0.4-3-x86_64 +installed = python-pydantic-2.11.7-1-any +installed = python-pydantic-core-2:2.33.2-2-x86_64 +installed = python-pydot-3.0.1-3-any +installed = python-pyee-11.1.0-2-any +installed = python-pyenchant-3.2.2-6-any +installed = python-pyfiglet-1.0.3-1-any +installed = python-pyflakes-3.3.2-1-any +installed = python-pygame-2.6.1-2-x86_64 +installed = python-pyglet-git-r6558.196678ba-1-any +installed = python-pygments-2.19.2-1-any +installed = python-pyjacklib-0.1.1-5-any +installed = python-pykakasi-2.3.0-2-any +installed = python-pymsgbox-1.0.9-2-any +installed = python-pynacl-1.5.0-3-x86_64 +installed = python-pyogg-0.6.14a1-1-any +installed = python-pyopenssl-25.1.0-1-any +installed = python-pyparsing-3.2.3-1-any +installed = python-pyperclip-1.9.0-3-any +installed = python-pyppmd-1.2.0-1-x86_64 +installed = python-pyproject-hooks-1.2.0-3-any +installed = python-pyqt5-5.15.11-2-x86_64 +installed = python-pyqt5-sip-12.17.0-1-x86_64 +installed = python-pyqt6-6.9.1-1-x86_64 +installed = python-pyqt6-sip-13.10.2-1-x86_64 +installed = python-pyqt6-webengine-6.9.0-1-x86_64 +installed = python-pyradios-1.0.2-1-any +installed = python-pyscreeze-1.0.1-1-any +installed = python-pyserial-3.5-7-any +installed = python-pysocks-1.7.1-10-any +installed = python-pystray-0.19.5-6-any +installed = python-pyte-0.8.2-4-any +installed = python-pytesseract-0.3.13-3-any +installed = python-pytest-1:8.4.1-1-any +installed = python-pythondialog-3.5.3-3-any +installed = python-pytweening-1.2.0-2-any +installed = python-pytz-2025.2-1-any +installed = python-pyudev-0.24.3-2-any +installed = python-pyusb-1.3.1-1-any +installed = python-pyxdg-0.28-4-any +installed = python-pyzmq-26.2.0-1-x86_64 +installed = python-pyzstd-0.17.0-1-x86_64 +installed = python-qrcode-8.2-1-any +installed = python-rapidfuzz-3.12.2-1-x86_64 +installed = python-rdflib-7.1.2-1-any +installed = python-referencing-0.36.2-1-any +installed = python-regex-2024.11.6-2-x86_64 +installed = python-requests-2.32.4-1-any +installed = python-requests-oauthlib-1.3.1-5-any +installed = python-requests-toolbelt-1.0.0-3-any +installed = python-resolvelib-1.2.0-2-any +installed = python-respx-0.22.0-3-any +installed = python-rich-14.1.0-1-any +installed = python-rpds-py-0.22.3-1-x86_64 +installed = python-rsa-4.9-6-any +installed = python-ruamel-yaml-0.18.10-1-any +installed = python-ruamel.yaml.clib-0.2.12-3-x86_64 +installed = python-s3transfer-0.13.1-1-any +installed = python-scikit-build-core-0.11.5-1-any +installed = python-scipy-1.16.1-1-x86_64 +installed = python-secretstorage-3.3.3-6-any +installed = python-service-identity-24.2.0-2-any +installed = python-setproctitle-1.3.6-1-x86_64 +installed = python-setuptools-1:80.9.0-1-any +installed = python-sgmllib3k-1.0.0-7-any +installed = python-shellingham-1.5.4-3-any +installed = python-simpleaudio-1.0.4-9-x86_64 +installed = python-six-1.17.0-1-any +installed = python-sniffio-1.3.1-4-any +installed = python-soco-0.30.10-1-any +installed = python-somecomfort-0.8.0-1-any +installed = python-sortedcontainers-2.4.0-7-any +installed = python-sounddevice-0.5.2-1-any +installed = python-soupsieve-2.6-2-any +installed = python-spake2-0.9-1-any +installed = python-speechrecognition-3.14.3-1-x86_64 +installed = python-sqlalchemy-2.0.41-1-x86_64 +installed = python-stack-data-0.6.3-4-any +installed = python-standard-aifc-3.13.0-3-any +installed = python-standard-cgi-3.13.0-3-any +installed = python-standard-chunk-3.13.0-3-any +installed = python-stevedore-5.4.0-1-any +installed = python-tabulate-0.9.0-5-any +installed = python-tensorboard_plugin_wit-1.8.1-10-any +installed = python-tensorflow-2.19.0-3-x86_64 +installed = python-termcolor-2.5.0-1-any +installed = python-textract-1.6.5-1-any +installed = python-texttable-1.7.0-3-any +installed = python-tiktoken-0.8.0-1-x86_64 +installed = python-tinycss2-1.4.0-2-any +installed = python-toml-0.10.2-12-any +installed = python-tomli-2.0.1-5-any +installed = python-tomlkit-0.13.3-1-any +installed = python-tornado-6.4.2-1-x86_64 +installed = python-tqdm-4.67.1-2-any +installed = python-traitlets-5.14.3-3-any +installed = python-trove-classifiers-2025.5.9.12-1-any +installed = python-twisted-24.3.0-4-any +installed = python-txaio-23.1.1-5-any +installed = python-txtorcon-24.8.0-1-any +installed = python-typeguard-4.4.4-1-any +installed = python-typing-inspection-0.4.1-1-any +installed = python-typing_extensions-4.14.1-1-any +installed = python-unrardll-0.1.7-4-x86_64 +installed = python-uritools-5.0.0-2-any +installed = python-urllib3-2.5.0-1-any +installed = python-urwid-3.0.2-1-any +installed = python-userpath-1.9.2-3-any +installed = python-virtualenv-20.28.0-1-any +installed = python-virtualenv-clone-0.5.7-6-any +installed = python-virtualenvwrapper-6.1.1-1-any +installed = python-vlc-3.0.21203-2-any +installed = python-watchdog-6.0.0-1-any +installed = python-wcwidth-0.2.13-3-any +installed = python-webencodings-0.5.1-12-any +installed = python-websocket-client-1.8.0-2-any +installed = python-werkzeug-3.1.3-1-any +installed = python-wheel-0.45.1-1-any +installed = python-whisper-1.1.10-1-any +installed = python-wrapt-1.16.0-4-x86_64 +installed = python-wsaccel-0.6.6-3-x86_64 +installed = python-wxpython-1:4.2.3-2-x86_64 +installed = python-xlib-0.33-4-any +installed = python-xmltodict-0.14.2-1-any +installed = python-xxhash-3.5.0-1-x86_64 +installed = python-yaml-6.0.2-2-x86_64 +installed = python-yarl-1.21.1-1-x86_64 +installed = python-zeroconf-0.147.0-2-x86_64 +installed = python-zipp-3.21.0-2-any +installed = python-zipstream-ng-1.8.0-4-any +installed = python-zope-interface-7.2-1-x86_64 +installed = python-zstandard-0.23.0-3-x86_64 +installed = qemu-audio-alsa-10.0.3-1-x86_64 +installed = qemu-audio-dbus-10.0.3-1-x86_64 +installed = qemu-audio-jack-10.0.3-1-x86_64 +installed = qemu-audio-oss-10.0.3-1-x86_64 +installed = qemu-audio-pa-10.0.3-1-x86_64 +installed = qemu-audio-pipewire-10.0.3-1-x86_64 +installed = qemu-audio-sdl-10.0.3-1-x86_64 +installed = qemu-audio-spice-10.0.3-1-x86_64 +installed = qemu-base-10.0.3-1-x86_64 +installed = qemu-block-curl-10.0.3-1-x86_64 +installed = qemu-block-dmg-10.0.3-1-x86_64 +installed = qemu-block-nfs-10.0.3-1-x86_64 +installed = qemu-block-ssh-10.0.3-1-x86_64 +installed = qemu-chardev-spice-10.0.3-1-x86_64 +installed = qemu-common-10.0.3-1-x86_64 +installed = qemu-desktop-10.0.3-1-x86_64 +installed = qemu-hw-display-qxl-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-gpu-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-gpu-gl-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-gpu-pci-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-gpu-pci-gl-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-gpu-pci-rutabaga-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-gpu-rutabaga-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-vga-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-vga-gl-10.0.3-1-x86_64 +installed = qemu-hw-display-virtio-vga-rutabaga-10.0.3-1-x86_64 +installed = qemu-hw-uefi-vars-10.0.3-1-x86_64 +installed = qemu-hw-usb-host-10.0.3-1-x86_64 +installed = qemu-hw-usb-redirect-10.0.3-1-x86_64 +installed = qemu-hw-usb-smartcard-10.0.3-1-x86_64 +installed = qemu-img-10.0.3-1-x86_64 +installed = qemu-system-x86-10.0.3-1-x86_64 +installed = qemu-system-x86-firmware-10.0.3-1-x86_64 +installed = qemu-ui-curses-10.0.3-1-x86_64 +installed = qemu-ui-dbus-10.0.3-1-x86_64 +installed = qemu-ui-egl-headless-10.0.3-1-x86_64 +installed = qemu-ui-gtk-10.0.3-1-x86_64 +installed = qemu-ui-opengl-10.0.3-1-x86_64 +installed = qemu-ui-sdl-10.0.3-1-x86_64 +installed = qemu-ui-spice-app-10.0.3-1-x86_64 +installed = qemu-ui-spice-core-10.0.3-1-x86_64 +installed = qemu-user-static-10.0.3-1-x86_64 +installed = qemu-user-static-binfmt-10.0.3-1-x86_64 +installed = qemu-vhost-user-gpu-10.0.3-1-x86_64 +installed = qhull-2020.2-5-x86_64 +installed = qjackctl-1.0.4-1-x86_64 +installed = qjoypad-4.3.1-1-x86_64 +installed = qpdf-12.2.0-1-x86_64 +installed = qrencode-4.1.1-4-x86_64 +installed = qt5-base-5.15.17+kde+r123-1-x86_64 +installed = qt5-declarative-5.15.17+kde+r21-1-x86_64 +installed = qt5-location-5.15.17+kde+r7-1-x86_64 +installed = qt5-multimedia-5.15.17+kde+r2-1-x86_64 +installed = qt5-remoteobjects-5.15.17-1-x86_64 +installed = qt5-speech-5.15.17+kde+r1-1-x86_64 +installed = qt5-svg-5.15.17+kde+r5-1-x86_64 +installed = qt5-tools-5.15.17+kde+r3-2-x86_64 +installed = qt5-translations-5.15.17-1-any +installed = qt5-wayland-5.15.17+kde+r57-1-x86_64 +installed = qt5-webchannel-5.15.17+kde+r3-1-x86_64 +installed = qt5-webengine-5.15.19-2-x86_64 +installed = qt5-websockets-5.15.17+kde+r2-1-x86_64 +installed = qt5-x11extras-5.15.17-1-x86_64 +installed = qt5-xmlpatterns-5.15.17-1-x86_64 +installed = qt6-5compat-6.9.1-1-x86_64 +installed = qt6-base-6.9.1-5-x86_64 +installed = qt6-declarative-6.9.1-2-x86_64 +installed = qt6-imageformats-6.9.1-1-x86_64 +installed = qt6-multimedia-6.9.1-1-x86_64 +installed = qt6-multimedia-ffmpeg-6.9.1-1-x86_64 +installed = qt6-positioning-6.9.1-1-x86_64 +installed = qt6-shadertools-6.9.1-1-x86_64 +installed = qt6-speech-6.9.1-1-x86_64 +installed = qt6-svg-6.9.1-1-x86_64 +installed = qt6-translations-6.9.1-1-any +installed = qt6-webchannel-6.9.1-1-x86_64 +installed = qt6-webengine-6.9.1-2-x86_64 +installed = quickemu-git-4.9.7.r47.gbd178bb-1-any +installed = quickgui-bin-1.2.10-1-x86_64 +installed = raptor-2.0.16-7-x86_64 +installed = rasqal-1:0.9.33-7-x86_64 +installed = rav1e-0.7.1-1-x86_64 +installed = rclone-1.70.3-1-x86_64 +installed = rdma-core-58.0-1-x86_64 +installed = re2-1:20240702-5-x86_64 +installed = readline-8.3.001-1-x86_64 +installed = realtime-privileges-4-3-any +installed = recode-3.7.15-1-x86_64 +installed = redland-1:1.0.17-9-x86_64 +installed = reflector-2023-3-any +installed = remind-5.3.5-1-x86_64 +installed = rename.pl-2.0.0-2-any +installed = retroarch-1.21.0-1-x86_64 +installed = rhash-1.4.4-1-x86_64 +installed = rhvoice-1.16.5-1-x86_64 +installed = rhvoice-language-english-1.16.5-1-x86_64 +installed = rhvoice-voice-lyubov-1.8.0-1-x86_64 +installed = ripgrep-14.1.1-1-x86_64 +installed = ripit-4.0.0_rc_20161009-8-any +installed = rndsig-6-1-any +installed = rnnoise-1:0.2-1-x86_64 +installed = rolldice-1.16-2-x86_64 +installed = rsync-3.4.1-2-x86_64 +installed = rtkit-0.13-3-x86_64 +installed = rtmpdump-1:2.4.r105.6f6bb13-1-x86_64 +installed = rubberband-4.0.0-1-x86_64 +installed = ruby-3.4.4-2-x86_64 +installed = rubygems-3.6.7-2-any +installed = run-parts-5.23.1-1-x86_64 +installed = runc-1.3.0-1-x86_64 +installed = rustup-1.28.2-3-x86_64 +installed = rutabaga-ffi-0.1.6-2-x86_64 +installed = sam-r64.a7b36ef-1-x86_64 +installed = samba-2:4.22.3-1-x86_64 +installed = sane-1.4.0-1-x86_64 +installed = sbc-2.1-1-x86_64 +installed = scrcpy-3.3.1-1-x86_64 +installed = screen-5.0.1-3-x86_64 +installed = scrot-1.12.1-1-x86_64 +installed = sdl12-compat-1.2.68-2-x86_64 +installed = sdl2-compat-2.32.56-2-x86_64 +installed = sdl2_image-2.8.8-1-x86_64 +installed = sdl2_mixer-2.8.1-2-x86_64 +installed = sdl2_ttf-2.24.0-1-x86_64 +installed = sdl3-3.2.20-1-x86_64 +installed = seabios-1.17.0-1-any +installed = secure-delete-3.1a-1-x86_64 +installed = sed-4.9-3-x86_64 +installed = semver-7.7.2-1-any +installed = serd-0.32.4-1-x86_64 +installed = sg3_utils-1.48-1-x86_64 +installed = sgtk-menu-1.4.1-1-x86_64 +installed = shaderc-2025.3-1-x86_64 +installed = shadow-4.18.0-1-x86_64 +installed = shared-mime-info-2.4-2-x86_64 +installed = shellcheck-0.11.0-3-x86_64 +installed = shiboken6-6.9.1-2-x86_64 +installed = simdjson-1:3.13.0-1-x86_64 +installed = simplescreenrecorder-git-0.4.4.r57.gc50e83e-1-x86_64 +installed = slack-libpurple-git-r375.ee43d55-1-x86_64 +installed = slang-2.3.3-4-x86_64 +installed = slim-1:1.4.0-1-x86_64 +installed = smbclient-2:4.22.3-1-x86_64 +installed = snappy-1.2.2-2-x86_64 +installed = socat-1.8.0.3-2-x86_64 +installed = socos-0.2.r33.g7719b54-2-any +installed = solaar-1.1.14-2-any +installed = solo1-0.1.1-5-any +installed = solo2-cli-0.2.2-1-x86_64 +installed = sord-0.16.18-1-x86_64 +installed = sound-theme-freedesktop-0.8-6-any +installed = soundtouch-2.4.0-1-x86_64 +installed = source-highlight-3.1.9-15-x86_64 +installed = sox-14.4.2+r184+gf3094754-7-x86_64 +installed = spandsp-0.0.6-5-x86_64 +installed = spdlog-1.15.3-1-x86_64 +installed = speech-dispatcher-0.12.1-1-x86_64 +installed = speedtest-cli-2.1.3-9-any +installed = speex-1.2.1-2-x86_64 +installed = speexdsp-1.2.1-2-x86_64 +installed = spell-1.1-1-x86_64 +installed = spice-0.16.0-2-x86_64 +installed = spice-gtk-0.42-4-x86_64 +installed = spice-protocol-0.14.5-1-any +installed = spice-vdagent-0.22.1-4-x86_64 +installed = spirv-tools-1:1.4.321.0-1-x86_64 +installed = sqlite-3.50.3-1-x86_64 +installed = squashfs-tools-4.7-1-x86_64 +installed = sratom-0.6.18-1-x86_64 +installed = srt-1.5.4-1-x86_64 +installed = startup-notification-0.12-8-x86_64 +installed = steam-1.0.0.82-2-x86_64 +installed = steamcmd-latest-5-x86_64 +installed = steamguard-cli-0.17.1-1-x86_64 +installed = strace-6.15-1-x86_64 +installed = strawberry-1.2.11-2-x86_64 +installed = sudo-1.9.17.p1-1-x86_64 +installed = suil-0.10.20-1-x86_64 +installed = surfraw-2.3.0-4-any +installed = svt-av1-3.0.2-1-x86_64 +installed = svt-hevc-1.5.1-3-x86_64 +installed = swtpm-0.10.1-1-x86_64 +installed = syncthing-1.30.0-1-x86_64 +installed = sysfsutils-2.1.1-2-x86_64 +installed = system-config-printer-1.5.18-5-x86_64 +installed = systemd-257.7-2-x86_64 +installed = systemd-libs-257.7-2-x86_64 +installed = systemd-sysvcompat-257.7-2-x86_64 +installed = taglib-2.1.1-1-x86_64 +installed = talloc-2.4.3-1-x86_64 +installed = tar-1.35-2-x86_64 +installed = tcl-8.6.16-1-x86_64 +installed = tdb-1.4.13-1-x86_64 +installed = tempy-git-1.2.1.r192.22db47e-1-any +installed = tenacity-1.3.4-4-x86_64 +installed = tensorboard-2.20.0-1-x86_64 +installed = tensorflow-2.19.0-3-x86_64 +installed = termdown-1.18.0-6-any +installed = tesseract-5.5.1-1-x86_64 +installed = tesseract-data-eng-2:4.1.0-4-any +installed = tesseract-data-osd-2:4.1.0-4-any +installed = tevent-1:0.17.0-1-x86_64 +installed = texinfo-7.2-1-x86_64 +installed = texlive-basic-2025.2-1-any +installed = texlive-bibtexextra-2025.2-1-any +installed = texlive-bin-2025.2-1-x86_64 +installed = texlive-binextra-2025.2-1-any +installed = texlive-context-2025.2-1-any +installed = texlive-fontsextra-2025.2-1-any +installed = texlive-fontsrecommended-2025.2-1-any +installed = texlive-fontutils-2025.2-1-any +installed = texlive-formatsextra-2025.2-1-any +installed = texlive-games-2025.2-1-any +installed = texlive-humanities-2025.2-1-any +installed = texlive-latex-2025.2-1-any +installed = texlive-latexextra-2025.2-1-any +installed = texlive-latexrecommended-2025.2-1-any +installed = texlive-luatex-2025.2-1-any +installed = texlive-mathscience-2025.2-1-any +installed = texlive-metapost-2025.2-1-any +installed = texlive-music-2025.2-1-any +installed = texlive-pictures-2025.2-1-any +installed = texlive-plaingeneric-2025.2-1-any +installed = texlive-pstricks-2025.2-1-any +installed = texlive-publishers-2025.2-1-any +installed = texlive-xetex-2025.2-1-any +installed = thorium-bin-2.4.1-1-x86_64 +installed = thunderbird-141.0-1-x86_64 +installed = tintin-2.02.51-1-x86_64 +installed = tinysparql-3.9.2-2-x86_64 +installed = tk-8.6.16-1-x86_64 +installed = toot-0.49.0-1-any +installed = tor-0.4.8.17-2-x86_64 +installed = torsocks-2.4.0-1-x86_64 +installed = tpm2-tss-4.1.3-1-x86_64 +installed = transfersh-1.4.1-1-any +installed = translate-shell-0.9.7.1-2-any +installed = tree-sitter-0.25.8-1-x86_64 +installed = tree-sitter-c-0.24.1-1-x86_64 +installed = tree-sitter-lua-0.4.0-1-x86_64 +installed = tree-sitter-markdown-0.5.0-1-x86_64 +installed = tree-sitter-query-0.6.2-1-x86_64 +installed = tree-sitter-vim-0.7.0-1-x86_64 +installed = tree-sitter-vimdoc-4.0.0-1-x86_64 +installed = tslib-1.23-1-x86_64 +installed = ttf-dejavu-2.37+18+g9b5d1b2f-7-any +installed = ttf-liberation-2.1.5-2-any +installed = tuyapi-cli-1.18.3-2-any +installed = twolame-0.4.0-4-x86_64 +installed = tzdata-2025b-1-x86_64 +installed = uchardet-0.0.8-3-x86_64 +installed = udisks2-2.10.1-6-x86_64 +installed = unarchiver-1.10.8-5-x86_64 +installed = unibilium-2.1.2-1-x86_64 +installed = unixodbc-2.3.12-3-x86_64 +installed = unoconv-0.9.0-1-any +installed = unp-1:2.0-1-any +installed = unrar-1:7.1.10-1-x86_64 +installed = unrtf-0.21.10-3-x86_64 +installed = unzip-6.0-23-x86_64 +installed = upower-1.90.9-1-x86_64 +installed = urlencode-1.6.0-1-x86_64 +installed = urlscan-1.0.7-1-any +installed = usbmuxd-1.1.1-4-x86_64 +installed = usbredir-0.15.0-1-x86_64 +installed = usbutils-018-1-x86_64 +installed = util-linux-2.41.1-1-x86_64 +installed = util-linux-libs-2.41.1-1-x86_64 +installed = v4l-utils-1.30.1-1-x86_64 +installed = vamp-plugin-sdk-2.10.0-3-x86_64 +installed = vapoursynth-R70-2-x86_64 +installed = vde2-2.3.3-8-x86_64 +installed = ventoy-1.1.05-3-x86_64 +installed = verdict-1.4.2-1-x86_64 +installed = vi-1:070224-6-x86_64 +installed = vid.stab-1.1.1-2-x86_64 +installed = vim-9.1.1552-1-x86_64 +installed = vim-runtime-9.1.1552-1-x86_64 +installed = vim-youcompleteme-git-r3232.131b1827-1-x86_64 +installed = virglrenderer-1.1.1-1-x86_64 +installed = virt-install-5.0.0-1-any +installed = virt-viewer-11.0-4-x86_64 +installed = virtio-win-0.1.271.1-1-any +installed = virtiofsd-1.13.2-1-x86_64 +installed = vita3k-git-r3807.4e526f0c8-1-x86_64 +installed = vivaldi-7.5.3735.58-1-x86_64 +installed = vlc-3.0.21-27-x86_64 +installed = vlc-cli-3.0.21-27-x86_64 +installed = vlc-gui-qt-3.0.21-27-x86_64 +installed = vlc-plugin-a52dec-3.0.21-27-x86_64 +installed = vlc-plugin-alsa-3.0.21-27-x86_64 +installed = vlc-plugin-archive-3.0.21-27-x86_64 +installed = vlc-plugin-dav1d-3.0.21-27-x86_64 +installed = vlc-plugin-dbus-3.0.21-27-x86_64 +installed = vlc-plugin-dbus-screensaver-3.0.21-27-x86_64 +installed = vlc-plugin-faad2-3.0.21-27-x86_64 +installed = vlc-plugin-flac-3.0.21-27-x86_64 +installed = vlc-plugin-gnutls-3.0.21-27-x86_64 +installed = vlc-plugin-inflate-3.0.21-27-x86_64 +installed = vlc-plugin-journal-3.0.21-27-x86_64 +installed = vlc-plugin-jpeg-3.0.21-27-x86_64 +installed = vlc-plugin-lua-3.0.21-27-x86_64 +installed = vlc-plugin-mpg123-3.0.21-27-x86_64 +installed = vlc-plugin-ogg-3.0.21-27-x86_64 +installed = vlc-plugin-opus-3.0.21-27-x86_64 +installed = vlc-plugin-png-3.0.21-27-x86_64 +installed = vlc-plugin-pulse-3.0.21-27-x86_64 +installed = vlc-plugin-shout-3.0.21-27-x86_64 +installed = vlc-plugin-speex-3.0.21-27-x86_64 +installed = vlc-plugin-tag-3.0.21-27-x86_64 +installed = vlc-plugin-theora-3.0.21-27-x86_64 +installed = vlc-plugin-twolame-3.0.21-27-x86_64 +installed = vlc-plugin-vorbis-3.0.21-27-x86_64 +installed = vlc-plugin-vpx-3.0.21-27-x86_64 +installed = vlc-plugin-xml-3.0.21-27-x86_64 +installed = vlc-plugins-base-3.0.21-27-x86_64 +installed = vlc-plugins-video-output-3.0.21-27-x86_64 +installed = vmaf-3.0.0-1-x86_64 +installed = volume_key-0.3.12-11-x86_64 +installed = vorbis-tools-1.4.3-1-x86_64 +installed = voxin-3.4-1-x86_64 +installed = voxin-speechd-3.4-1-x86_64 +installed = voxin-speechd-conf-3.4-1-x86_64 +installed = vte-common-0.80.3-1-x86_64 +installed = vte3-0.80.3-1-x86_64 +installed = vtk-9.5.0-4-x86_64 +installed = vulkan-icd-loader-1.4.321.0-1-x86_64 +installed = w3m-0.5.3.git20230713_1-1-x86_64 +installed = wavpack-5.8.1-1-x86_64 +installed = wayland-1.24.0-1-x86_64 +installed = webkit2gtk-4.1-2.48.5-1-x86_64 +installed = webp-pixbuf-loader-0.2.7-1-x86_64 +installed = webrtc-audio-processing-0.3-0.3.1-6-x86_64 +installed = webrtc-audio-processing-1-1.3-5-x86_64 +installed = wget-1.25.0-2-x86_64 +installed = which-2.23-1-x86_64 +installed = whois-5.6.1-1-x86_64 +installed = wildmidi-0.4.6-1-x86_64 +installed = wine-10.0-1-x86_64 +installed = wine-gecko-2.47.4-2-x86_64 +installed = wine-mono-10.1.0-1-x86_64 +installed = winetricks-20250102-1-x86_64 +installed = wireguard-tools-1.0.20250521-1-x86_64 +installed = wireless-regdb-2025.07.10-1-any +installed = wireplumber-0.5.10-1-x86_64 +installed = wmctrl-1.07-6-x86_64 +installed = wmname-0.1-6-x86_64 +installed = woff2-1.0.2-6-x86_64 +installed = wolfssl-5.8.2-1-x86_64 +installed = words-2.1-8-any +installed = wpa_supplicant-2:2.11-3-x86_64 +installed = wxwidgets-common-3.2.8.1-2-x86_64 +installed = wxwidgets-gtk3-3.2.8.1-2-x86_64 +installed = x264-3:0.164.r3108.31e19f9-3-x86_64 +installed = x265-4.1-1-x86_64 +installed = xboxdrv-stable-git-0.8.8.r18.g662952a-1-x86_64 +installed = xcb-proto-1.17.0-3-any +installed = xcb-util-0.4.1-2-x86_64 +installed = xcb-util-cursor-0.1.5-1-x86_64 +installed = xcb-util-image-0.4.1-3-x86_64 +installed = xcb-util-keysyms-0.4.1-5-x86_64 +installed = xcb-util-renderutil-0.3.10-2-x86_64 +installed = xcb-util-wm-0.4.2-2-x86_64 +installed = xcb-util-xrm-1.3-3-x86_64 +installed = xclip-0.13-6-x86_64 +installed = xdg-dbus-proxy-0.1.6-1-x86_64 +installed = xdg-desktop-portal-1.20.3-1-x86_64 +installed = xdg-desktop-portal-gtk-1.15.3-1-x86_64 +installed = xdg-user-dirs-0.18-2-x86_64 +installed = xdg-utils-1.2.1-1-any +installed = xdotool-3.20211022.1-2-x86_64 +installed = xf86-input-libinput-1.5.0-1-x86_64 +installed = xf86-video-vesa-2.6.0-2-x86_64 +installed = xfce4-notifyd-0.9.7-1-x86_64 +installed = xfce4-screensaver-4.20.0-1-x86_64 +installed = xfconf-4.20.0-2-x86_64 +installed = xkeyboard-config-2.45-1-any +installed = xmlsec-1.3.7-2-x86_64 +installed = xorg-bdftopcf-1.1.2-1-x86_64 +installed = xorg-docs-1.7.3-2-any +installed = xorg-font-util-1.4.1-2-x86_64 +installed = xorg-fonts-100dpi-1.0.4-3-any +installed = xorg-fonts-75dpi-1.0.4-2-any +installed = xorg-fonts-alias-100dpi-1.0.5-1-any +installed = xorg-fonts-alias-75dpi-1.0.5-1-any +installed = xorg-fonts-encodings-1.1.0-1-any +installed = xorg-iceauth-1.0.10-1-x86_64 +installed = xorg-mkfontscale-1.2.3-1-x86_64 +installed = xorg-server-21.1.18-2-x86_64 +installed = xorg-server-common-21.1.18-2-x86_64 +installed = xorg-server-devel-21.1.18-2-x86_64 +installed = xorg-server-xephyr-21.1.18-2-x86_64 +installed = xorg-server-xnest-21.1.18-2-x86_64 +installed = xorg-server-xvfb-21.1.18-2-x86_64 +installed = xorg-sessreg-1.1.4-1-x86_64 +installed = xorg-setxkbmap-1.3.4-2-x86_64 +installed = xorg-smproxy-1.0.8-1-x86_64 +installed = xorg-util-macros-1.20.2-1-any +installed = xorg-x11perf-1.7.0-1-x86_64 +installed = xorg-xauth-1.1.4-1-x86_64 +installed = xorg-xbacklight-1.2.4-1-x86_64 +installed = xorg-xcmsdb-1.0.7-1-x86_64 +installed = xorg-xcursorgen-1.0.9-1-x86_64 +installed = xorg-xdpyinfo-1.3.4-2-x86_64 +installed = xorg-xdriinfo-1.0.7-2-x86_64 +installed = xorg-xev-1.2.6-1-x86_64 +installed = xorg-xgamma-1.0.7-2-x86_64 +installed = xorg-xhost-1.0.10-1-x86_64 +installed = xorg-xinit-1.4.4-1-x86_64 +installed = xorg-xinput-1.6.4-2-x86_64 +installed = xorg-xkbcomp-1.4.7-1-x86_64 +installed = xorg-xkbevd-1.1.6-1-x86_64 +installed = xorg-xkbutils-1.0.6-1-x86_64 +installed = xorg-xkill-1.0.6-2-x86_64 +installed = xorg-xlsatoms-1.1.4-2-x86_64 +installed = xorg-xlsclients-1.1.5-2-x86_64 +installed = xorg-xmessage-1.0.7-1-x86_64 +installed = xorg-xmodmap-1.0.11-2-x86_64 +installed = xorg-xpr-1.2.0-1-x86_64 +installed = xorg-xprop-1.2.8-1-x86_64 +installed = xorg-xrandr-1.5.3-1-x86_64 +installed = xorg-xrdb-1.2.2-2-x86_64 +installed = xorg-xrefresh-1.1.0-1-x86_64 +installed = xorg-xset-1.2.5-2-x86_64 +installed = xorg-xsetroot-1.1.3-2-x86_64 +installed = xorg-xvinfo-1.1.5-2-x86_64 +installed = xorg-xwayland-24.1.8-1-x86_64 +installed = xorg-xwd-1.0.9-2-x86_64 +installed = xorg-xwininfo-1.1.6-2-x86_64 +installed = xorg-xwud-1.0.7-1-x86_64 +installed = xorgproto-2024.1-2-any +installed = xsane-0.999-7-x86_64 +installed = xvidcore-1.3.7-3-x86_64 +installed = xxhash-0.8.3-1-x86_64 +installed = xz-5.8.1-1-x86_64 +installed = yad-14.1-2-x86_64 +installed = yajl-2.1.0-6-x86_64 +installed = yaml-cpp-0.8.0-2-x86_64 +installed = yarn-1.22.22-2-any +installed = yay-12.5.0-1-x86_64 +installed = youtube-dl-git-2021.12.17.r404.g420d53387c-1-any +installed = yt-cli-0.2.3-1-any +installed = yt-dlp-2025.07.21-1-any +installed = yyjson-0.11.1-1-x86_64 +installed = zbar-0.23.93-4-x86_64 +installed = zdbsp-1.19-2-x86_64 +installed = zenity-4.1.99-2-x86_64 +installed = zeromq-4.3.5-2-x86_64 +installed = zimg-3.0.5-1-x86_64 +installed = zip-3.0-11-x86_64 +installed = zix-0.6.2-1-x86_64 +installed = zlib-1:1.3.1-2-x86_64 +installed = zlib-ng-2.2.4-1-x86_64 +installed = zmusic-1.1.14.r8.g6928b86-1-x86_64 +installed = zoom-6.5.8-1-x86_64 +installed = zopfli-1.0.3-4-x86_64 +installed = zspotify-0.5.2-5-x86_64 +installed = zstd-1.5.7-2-x86_64 +installed = zsync-0.6.2-5-x86_64 +installed = zvbi-0.2.44-1-x86_64 +installed = zxing-cpp-2.3.0-5-x86_64 +installed = zziplib-0.13.80-1-x86_64 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/.MTREE b/distro-packages/Arch-Linux/pkg/cthulhu/.MTREE new file mode 100644 index 0000000000000000000000000000000000000000..897ac2212cdabb4e901a6c5d3df56e4f8c13e518 GIT binary patch literal 30876 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 None: + """Sets up the GUI for the actions list.""" + + self.set_title(guilabels.KB_GROUP_ACTIONS) + self.set_modal(True) + self.set_decorated(False) + self.set_skip_taskbar_hint(True) + self.set_skip_pager_hint(True) + self.set_type_hint(Gdk.WindowTypeHint.DIALOG) + # Note: set_window_position is deprecated, using move() instead + self.move(100, 100) # Position window at reasonable location + self.set_default_size(400, 300) + + # Create scrolled window + scrolled = Gtk.ScrolledWindow() + scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + self.add(scrolled) + + # Create list box + self._listbox = Gtk.ListBox() + self._listbox.set_selection_mode(Gtk.SelectionMode.SINGLE) + self._listbox.connect("row-activated", self._on_row_activated) + scrolled.add(self._listbox) + + # Connect key events + self.connect("key-press-event", self._on_key_press) + self.connect("destroy", self._on_destroy) + + self.show_all() + + def _on_key_press(self, widget, event) -> bool: + """Handles key press events.""" + + if event.keyval == Gdk.KEY_Escape: + self.destroy() + return True + return False + + def _on_row_activated(self, listbox, row) -> None: + """Handles row activation (Enter or double-click).""" + + if row is not None: + action_index = row.get_index() + if 0 <= action_index < len(self._actions): + action_name = self._actions[action_index] + self._presenter._perform_action(action_name) + + def _on_destroy(self, widget) -> None: + """Handles window destruction.""" + + GLib.idle_add(self._presenter._clear_gui_and_restore_focus) + + def populate_actions(self, actions: list[str]) -> None: + """Populates the list with accessible actions.""" + + self._actions = actions + + # Clear existing items + for child in self._listbox.get_children(): + self._listbox.remove(child) + + # Add actions to list + for action in actions: + label = Gtk.Label(label=action) + label.set_xalign(0.0) # Left align + label.set_margin_left(10) + label.set_margin_right(10) + label.set_margin_top(5) + label.set_margin_bottom(5) + + self._listbox.add(label) + + # Select first item + if actions: + first_row = self._listbox.get_row_at_index(0) + if first_row: + self._listbox.select_row(first_row) + first_row.grab_focus() + + self.show_all() + + +class ActionPresenter: + """Provides a list for performing accessible actions on an object.""" + + def __init__(self): + self._handlers = None + self._bindings = None + self._gui = None + self._obj = None + self._window = None + + # Initialize handlers + self._handlers = self.get_handlers(True) + # _bindings will be initialized lazily in get_bindings() + + def get_handlers(self, refresh: bool = False) -> dict: + """Returns a dictionary of input event handlers.""" + + if self._handlers is None or refresh: + msg = "ACTION PRESENTER: Getting input event handlers." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._setup_handlers() + + return self._handlers + + def get_bindings(self, refresh: bool = False, is_desktop: bool = True) -> keybindings.KeyBindings: + """Returns keybindings for this presenter.""" + + if self._bindings is None or refresh: + msg = "ACTION PRESENTER: Getting key bindings." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._setup_bindings() + + return self._bindings + + def _setup_handlers(self) -> None: + """Sets up input event handlers for this presenter.""" + + msg = "ACTION PRESENTER: Setting up handlers." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self._handlers = {} + + self._handlers["show_actions_list"] = \ + input_event.InputEventHandler( + self.show_actions_list, + cmdnames.SHOW_ACTIONS_LIST) + + msg = "ACTION PRESENTER: Handlers set up." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _setup_bindings(self) -> None: + """Sets up key bindings for this presenter.""" + + msg = "ACTION PRESENTER: Setting up bindings." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self._bindings = keybindings.KeyBindings() + self._bindings.add(keybindings.KeyBinding( + "a", + keybindings.defaultModifierMask, + keybindings.CTHULHU_SHIFT_MODIFIER_MASK, + self._handlers["show_actions_list"])) + + msg = "ACTION PRESENTER: Bindings set up." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _restore_focus(self) -> None: + """Restores focus to the object associated with the actions list.""" + + tokens = ["ACTION PRESENTER: Restoring focus to", self._obj, "in", self._window] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + reason = "Action Presenter list is being destroyed" + app = AXObject.get_application(self._obj) + script = script_manager.getManager().getScript(app, self._obj) + script_manager.getManager().setActiveScript(script, reason) + + # Update Cthulhu state + cthulhu_state.activeWindow = self._window + cthulhu_state.locusOfFocus = self._obj + + def _clear_gui_and_restore_focus(self) -> None: + """Clears the GUI reference and then restores focus.""" + + self._gui = None + self._restore_focus() + + def _perform_action(self, action: str) -> None: + """Attempts to perform the named action.""" + + if self._gui is None: + msg = "ACTION PRESENTER: _perform_action called when self._gui is None." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + self._gui.hide() + result = AXObject.do_named_action(self._obj, action) + tokens = ["ACTION PRESENTER: Performing", action, "on", self._obj, "succeeded:", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # Use idle_add for asynchronous destruction to allow action to complete + GLib.idle_add(self._gui.destroy) + + def present_with_time(self, obj, start_time: float) -> bool: + """Presents accessible actions for the given object with timing.""" + + try: + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: present_with_time called with obj: {obj}", True) + + if self._gui is not None: + msg = "ACTION PRESENTER: GUI already exists." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if obj is None: + debug.printMessage(debug.LEVEL_INFO, "ACTION PRESENTER: obj is None, using locusOfFocus", True) + obj = cthulhu_state.locusOfFocus + + if obj is None: + debug.printMessage(debug.LEVEL_INFO, "ACTION PRESENTER: No object found, presenting NO_ACCESSIBLE_ACTIONS", True) + full_message = messages.NO_ACCESSIBLE_ACTIONS + cthulhu.presentMessage(full_message) + return False + + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: Getting actions for object: {obj}", True) + actions = AXObject.get_action_names(obj) + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: Found {len(actions) if actions else 0} actions: {actions}", True) + + if not actions: + debug.printMessage(debug.LEVEL_INFO, "ACTION PRESENTER: No actions found, presenting NO_ACCESSIBLE_ACTIONS", True) + full_message = messages.NO_ACCESSIBLE_ACTIONS + cthulhu.presentMessage(full_message) + return False + + debug.printMessage(debug.LEVEL_INFO, "ACTION PRESENTER: Creating GUI", True) + self._obj = obj + self._window = cthulhu_state.activeWindow + + self._gui = ActionList(self) + self._gui.populate_actions(actions) + + debug.printMessage(debug.LEVEL_INFO, "ACTION PRESENTER: GUI created successfully", True) + return True + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: ERROR in present_with_time: {e}", True) + import traceback + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: Traceback: {traceback.format_exc()}", True) + return False + + def show_actions_list(self, script: script.Script = None, input_event: input_event.InputEvent = None) -> bool: + """Shows the accessible actions list.""" + + try: + msg = f"ACTION PRESENTER: show_actions_list called! input_event: {input_event}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + start_time = time.time() + + # Get object from input event if available, otherwise let present_with_time handle it + obj = input_event.getObject() if input_event else None + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: Object from input_event: {obj}", True) + + result = self.present_with_time(obj, start_time) + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: show_actions_list returning: {result}", True) + return result + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: ERROR in show_actions_list: {e}", True) + import traceback + debug.printMessage(debug.LEVEL_INFO, f"ACTION PRESENTER: Traceback: {traceback.format_exc()}", True) + return False + + +_presenter = ActionPresenter() + +def getPresenter() -> ActionPresenter: + """Returns the Action Presenter singleton.""" + return _presenter \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_collection.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_collection.py new file mode 100644 index 0000000..f3251a2 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_collection.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for obtaining objects via the collection interface. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import time + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from .ax_object import AXObject + + +class AXCollection: + """Utilities for obtaining objects via the collection interface.""" + + # Too many arguments and too many local variables. + # This function wraps Atspi.MatchRule.new which has all the arguments. + # pylint: disable=R0913,R0914 + @staticmethod + def create_match_rule(states=[], + state_match_type=Atspi.CollectionMatchType.ALL, + attributes=[], + attribute_match_type=Atspi.CollectionMatchType.ANY, + roles=[], + role_match_type=Atspi.CollectionMatchType.ANY, + interfaces=[], + interface_match_type=Atspi.CollectionMatchType.ALL, + invert=False): + """Creates a match rule based on the supplied criteria.""" + + state_set = Atspi.StateSet() + if states: + for state in states: + state_set.add(state) + + attributes_dict = {} + if attributes: + for attr in attributes: + key, value = attr.split(":", 1) + value = value.replace(":", r"\:") + if key in attributes_dict: + attributes_dict[key] = attributes_dict[key] + ":" + value + else: + attributes_dict[key] = value + + try: + rule = Atspi.MatchRule.new(state_set, + state_match_type, + attributes_dict, + attribute_match_type, + roles, + role_match_type, + interfaces, + interface_match_type, + invert) + except Exception as error: + tokens = ["AXCollection: Exception in create_match_rule:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return rule + # pylint: enable=R0913,R0914 + + @staticmethod + def get_all_matches(obj, rule, order=Atspi.CollectionSortOrder.CANONICAL): + """Returns a list of objects matching the specified rule.""" + + if not AXObject.supports_collection(obj): + return [] + + if rule is None: + return [] + + start = time.time() + try: + # 0 means no limit on the number of results + # The final argument, traverse, is not supported but is expected. + matches = Atspi.Collection.get_matches(obj, rule, order, 0, True) + except Exception as error: + tokens = ["AXCollection: Exception in get_all_matches:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + msg = f"AXCollection: {len(matches)} match(es) found in {time.time() - start:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return matches + + @staticmethod + def get_first_match(obj, rule, order=Atspi.CollectionSortOrder.CANONICAL): + """Returns the first object matching the specified rule.""" + + if not AXObject.supports_collection(obj): + return None + + if rule is None: + return None + + start = time.time() + try: + # 1 means limit the number of results to 1 + # The final argument, traverse, is not supported but is expected. + matches = Atspi.Collection.get_matches(obj, rule, order, 1, True) + except Exception as error: + tokens = ["AXCollection: Exception in get_first_match:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + match = None + if matches: + match = matches[0] + + msg = f"AXCollection: found {match} in {time.time() - start:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return match diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_event_synthesizer.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_event_synthesizer.py new file mode 100644 index 0000000..ccb1c32 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_event_synthesizer.py @@ -0,0 +1,586 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides support for synthesizing accessible input events.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2018-2023 Igalia, S.L." +__license__ = "LGPL" + +import time + +import gi + +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + +from . import debug +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +class AXEventSynthesizer: + """Provides support for synthesizing accessible input events.""" + + _banner = None + + @staticmethod + def _get_mouse_coordinates(): + """Returns the current mouse coordinates.""" + + root_window = Gtk.Window().get_screen().get_root_window() + window, x_coord, y_coord, modifiers = root_window.get_pointer() + tokens = ["AXEventSynthesizer: Mouse coordinates:", x_coord, ",", y_coord] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return x_coord, y_coord + + @staticmethod + def _generate_mouse_event(x_coord, y_coord, event): + """Synthesize a mouse event at a specific screen coordinate.""" + + old_x, old_y = AXEventSynthesizer._get_mouse_coordinates() + tokens = ["AXEventSynthesizer: Generating", event, "mouse event at", x_coord, ",", y_coord] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + try: + success = Atspi.generate_mouse_event(x_coord, y_coord, event) + except Exception as error: + tokens = ["AXEventSynthesizer: Exception in _generate_mouse_event:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + success = False + else: + tokens = ["AXEventSynthesizer: Atspi.generate_mouse_event returned", success] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # There seems to be a timeout / lack of reply from this blocking call. + # But often the mouse event is successful. Pause briefly before checking. + time.sleep(1) + + new_x, new_y = AXEventSynthesizer._get_mouse_coordinates() + if old_x == new_x and old_y == new_y and (old_x, old_y) != (x_coord, y_coord): + msg = "AXEventSynthesizer: Mouse event possible failure. Pointer didn't move" + debug.println(debug.LEVEL_INFO, msg, True) + return False + + return True + + @staticmethod + def _intersection(extents1, extents2): + """Returns the bounding box containing the intersection of the two boxes.""" + + x_coord1, y_coord1, width1, height1 = extents1 + x_coord2, y_coord2, width2, height2 = extents2 + + x_points1 = range(x_coord1, x_coord1 + width1 + 1) + x_points2 = range(x_coord2, x_coord2 + width2 + 1) + x_intersection = sorted(set(x_points1).intersection(set(x_points2))) + + y_points1 = range(y_coord1, y_coord1 + height1 + 1) + y_points2 = range(y_coord2, y_coord2 + height2 + 1) + y_intersection = sorted(set(y_points1).intersection(set(y_points2))) + + if not (x_intersection and y_intersection): + return 0, 0, 0, 0 + + x_coord = x_intersection[0] + y_coord = y_intersection[0] + width = x_intersection[-1] - x_coord + height = y_intersection[-1] - y_coord + return x_coord, y_coord, width, height + + @staticmethod + def _extents_at_caret(obj): + """Returns the character extents of obj at the current caret offset.""" + + try: + text = obj.queryText() + extents = text.getCharacterExtents(text.caretOffset, Atspi.CoordType.SCREEN) + except Exception: + tokens = ["ERROR: Exception getting character extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return 0, 0, 0, 0 + + return extents + + @staticmethod + def _object_extents(obj): + """Returns the bounding box associated with obj.""" + + try: + extents = obj.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["ERROR: Exception getting extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return 0, 0, 0, 0 + + return extents + + @staticmethod + def _mouse_event_on_character(obj, event): + """Performs the specified mouse event on the current character in obj.""" + + extents = AXEventSynthesizer._extents_at_caret(obj) + if extents == (0, 0, 0, 0): + return False + + obj_extents = AXEventSynthesizer._object_extents(obj) + intersection = AXEventSynthesizer._intersection(extents, obj_extents) + if intersection == (0, 0, 0, 0): + tokens = ["AXEventSynthesizer:", obj, "'s caret", extents, "not in obj", obj_extents] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + x_coord = max(extents[0], extents[0] + (extents[2] / 2) - 1) + y_coord = extents[1] + extents[3] / 2 + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, event) + + @staticmethod + def _mouse_event_on_object(obj, event): + """Performs the specified mouse event on obj.""" + + extents = AXEventSynthesizer._object_extents(obj) + if extents == (0, 0, 0, 0): + return False + + x_coord = extents.x + extents.width/2 + y_coord = extents.y + extents.height/2 + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, event) + + @staticmethod + def route_to_character(obj): + """Routes the pointer to the current character in obj.""" + + tokens = ["AXEventSynthesizer: Attempting to route to character in", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return AXEventSynthesizer._mouse_event_on_character(obj, "abs") + + @staticmethod + def route_to_object(obj): + """Moves the mouse pointer to the center of obj.""" + + tokens = ["AXEventSynthesizer: Attempting to route to", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return AXEventSynthesizer._mouse_event_on_object(obj, "abs") + + @staticmethod + def route_to_point(x_coord, y_coord): + """Routes the pointer to the specified coordinates.""" + + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, "abs") + + @staticmethod + def click_character(obj, button=1): + """Single click on the current character in obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_character(obj, f"b{button}c") + + @staticmethod + def click_object(obj, button=1): + """Single click on obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_object(obj, f"b{button}c") + + @staticmethod + def click_point(x_coord, y_coord, button=1): + """Single click on the given point using the specified button.""" + + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, f"b{button}c") + + @staticmethod + def double_click_character(obj, button=1): + """Double click on the current character in obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_character(obj, f"b{button}d") + + @staticmethod + def double_click_object(obj, button=1): + """Double click on obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_object(obj, f"b{button}d") + + @staticmethod + def double_click_point(x_coord, y_coord, button=1): + """Double click on the given point using the specified button.""" + + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, f"b{button}d") + + @staticmethod + def press_at_character(obj, button=1): + """Performs a press on the current character in obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_character(obj, f"b{button}p") + + @staticmethod + def press_at_object(obj, button=1): + """Performs a press on obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_object(obj, f"b{button}p") + + @staticmethod + def press_at_point(x_coord, y_coord, button=1): + """Performs a press on the given point using the specified button.""" + + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, f"b{button}p") + + @staticmethod + def release_at_character(obj, button=1): + """Performs a release on the current character in obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_character(obj, f"b{button}r") + + @staticmethod + def release_at_object(obj, button=1): + """Performs a release on obj using the specified button.""" + + return AXEventSynthesizer._mouse_event_on_object(obj, f"b{button}r") + + @staticmethod + def release_at_point(x_coord, y_coord, button=1): + """Performs a release on the given point using the specified button.""" + + return AXEventSynthesizer._generate_mouse_event(x_coord, y_coord, f"b{button}r") + + @staticmethod + def _scroll_substring_to_location(obj, location, start_offset, end_offset): + """Attempts to scroll the given substring to the specified location.""" + + try: + text = obj.queryText() + if not text.characterCount: + return False + if start_offset is None: + start_offset = 0 + if end_offset is None: + end_offset = text.characterCount - 1 + result = text.scrollSubstringTo(start_offset, end_offset, location) + except NotImplementedError: + tokens = ["AXEventSynthesizer: Text interface not implemented for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + except Exception: + msg = ( + f"AXEventSynthesizer: Exception scrolling {obj} ({start_offset}, {end_offset}) " + f"to {location.value_name}." + ) + debug.println(debug.LEVEL_INFO, msg, True) + return False + + msg = ( + f"AXEventSynthesizer: scrolled {obj} substring ({start_offset}, {end_offset}) " + f"to {location.value_name}: {result}" + ) + debug.println(debug.LEVEL_INFO, msg, True) + return result + + @staticmethod + def _scroll_object_to_location(obj, location): + """Attempts to scroll obj to the specified location.""" + + try: + result = obj.queryComponent().scrollTo(location) + except NotImplementedError: + tokens = ["AXEventSynthesizer: Component interface not implemented for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + except Exception: + tokens = ["AXEventSynthesizer: Exception scrolling", + obj, "to", location.value_name, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["AXEventSynthesizer: scrolled", obj, "to", location.value_name, ":", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + @staticmethod + def _scroll_to_location(obj, location, start_offset=None, end_offset=None): + """Attempts to scroll to the specified location.""" + + try: + component = obj.queryComponent() + except Exception: + tokens = ["AXEventSynthesizer: Exception querying component of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + before = component.getExtents(Atspi.CoordType.SCREEN) + + if not AXEventSynthesizer._scroll_substring_to_location( + obj, location, start_offset, end_offset): + AXEventSynthesizer._scroll_object_to_location(obj, location) + + after = component.getExtents(Atspi.CoordType.SCREEN) + msg = ( + f"AXEventSynthesizer: Before scroll: {before[0]}, {before[1]}. " + f"After scroll: {after[0]}, {after[1]}." + ) + debug.println(debug.LEVEL_INFO, msg, True) + + @staticmethod + def _scroll_substring_to_point(obj, x_coord, y_coord, start_offset, end_offset): + """Attempts to scroll the given substring to the specified location.""" + + try: + text = obj.queryText() + if not text.characterCount: + return False + if start_offset is None: + start_offset = 0 + if end_offset is None: + end_offset = text.characterCount - 1 + result = text.scrollSubstringToPoint( + start_offset, end_offset, Atspi.CoordType.SCREEN, x_coord, y_coord) + except NotImplementedError: + tokens = ["AXEventSynthesizer: Text interface not implemented for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + except Exception: + msg = ( + f"AXEventSynthesizer: Exception scrolling {obj} ({start_offset}, {end_offset}) " + f"to {x_coord}, {y_coord}" + ) + debug.println(debug.LEVEL_INFO, msg, True) + return False + + msg = "AXEventSynthesizer: scrolled %s (%i, %i) to %i, %i: %s" % \ + (obj, start_offset, end_offset, x_coord, y_coord, result) + debug.println(debug.LEVEL_INFO, msg, True) + return result + + @staticmethod + def _scroll_object_to_point(obj, x_coord, y_coord): + """Attempts to scroll obj to the specified point.""" + + try: + result = obj.queryComponent().scrollToPoint(Atspi.CoordType.SCREEN, x_coord, y_coord) + except NotImplementedError: + tokens = ["AXEventSynthesizer: Component interface not implemented for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + except Exception: + tokens = ["AXEventSynthesizer: Exception scrolling", obj, "to", x_coord, ",", y_coord] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["AXEventSynthesizer: scrolled", obj, "to", x_coord, ",", y_coord, ":", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + @staticmethod + def _scroll_to_point(obj, x_coord, y_coord, start_offset=None, end_offset=None): + """Attempts to scroll obj to the specified point.""" + + try: + component = obj.queryComponent() + except Exception: + tokens = ["AXEventSynthesizer: Exception querying component of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + before = component.getExtents(Atspi.CoordType.SCREEN) + + if not AXEventSynthesizer._scroll_substring_to_point( + obj, x_coord, y_coord, start_offset, end_offset): + AXEventSynthesizer._scroll_object_to_point(obj, x_coord, y_coord) + + after = component.getExtents(Atspi.CoordType.SCREEN) + msg = ( + f"AXEventSynthesizer: Before scroll: {before[0]}, {before[1]}. " + f"After scroll: {after[0]}, {after[1]}." + ) + debug.println(debug.LEVEL_INFO, msg, True) + + @staticmethod + def scroll_into_view(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj into view.""" + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.ANYWHERE, start_offset, end_offset) + + @staticmethod + def _containing_document(obj): + """Returns the document containing obj""" + + document = AXObject.find_ancestor(obj, AXUtilities.is_document) + while document: + ancestor = AXObject.find_ancestor(document, AXUtilities.is_document) + if ancestor is None or ancestor == document: + break + document = ancestor + + return document + + @staticmethod + def _get_accessible_at_point(root, x_coord, y_coord): + """"Returns the accessible in root at the specified point.""" + + try: + result = root.queryComponent().getAccessibleAtPoint( + x_coord, y_coord, Atspi.CoordType.SCREEN) + except NotImplementedError: + tokens = ["AXEventSynthesizer: Component interface not implemented for", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + except Exception: + msg = ( + f"AXEventSynthesizer: Exception getting accessible at " + f"{x_coord}, {y_coord} for {root}" + ) + debug.println(debug.LEVEL_INFO, msg, True) + return None + + tokens = ["AXEventSynthesizer: Accessible at", + x_coord, ",", y_coord, "in", root, ":", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + @staticmethod + def _get_obscuring_banner(obj): + """"Returns the banner obscuring obj from view.""" + + document = AXEventSynthesizer._containing_document(obj) + if not document: + tokens = ["AXEventSynthesizer: No obscuring banner found for", obj, ". No document."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if not AXObject.supports_component(document): + tokens = ["AXEventSynthesizer: No obscuring banner found for", obj, ". No doc iface."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + obj_x, obj_y, obj_width, obj_height = AXEventSynthesizer._object_extents(obj) + doc_x, doc_y, doc_width, doc_height = AXEventSynthesizer._object_extents(document) + + left = AXEventSynthesizer._get_accessible_at_point(document, doc_x, obj_y) + right = AXEventSynthesizer._get_accessible_at_point(document, doc_x + doc_width, obj_y) + if not (left and right and left == right != document): + tokens = ["AXEventSynthesizer: No obscuring banner found for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + tokens = ["AXEventSynthesizer:", obj, "believed to be obscured by banner", left] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return left + + @staticmethod + def _scroll_below_banner(obj, banner, start_offset, end_offset, margin=25): + """Attempts to scroll obj below banner.""" + + obj_x, obj_y, obj_width, obj_height = AXEventSynthesizer._object_extents(obj) + banner_x, banner_y, banner_width, banner_height = AXEventSynthesizer._object_extents(banner) + msg = ( + f"AXEventSynthesizer: Extents of banner: " + f"({banner_x}, {banner_y}, {banner_width}, {banner_height})" + ) + debug.println(debug.LEVEL_INFO, msg, True) + AXEventSynthesizer._scroll_to_point( + obj, obj_x, banner_y + banner_height + margin, start_offset, end_offset) + + @staticmethod + def scroll_to_top_edge(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj to the top edge.""" + + if AXEventSynthesizer._banner and not AXObject.is_dead(AXEventSynthesizer._banner): + msg = ( + f"AXEventSynthesizer: Suspected existing banner found: " + f"{AXEventSynthesizer._banner}" + ) + debug.println(debug.LEVEL_INFO, msg, True) + AXEventSynthesizer._scroll_below_banner( + obj, AXEventSynthesizer._banner, start_offset, end_offset) + return + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.TOP_EDGE, start_offset, end_offset) + + AXEventSynthesizer._banner = AXEventSynthesizer._get_obscuring_banner(obj) + if AXEventSynthesizer._banner: + msg = f"AXEventSynthesizer: Re-scrolling {obj} due to banner" + AXEventSynthesizer._scroll_below_banner( + obj, AXEventSynthesizer._banner, start_offset, end_offset) + debug.println(debug.LEVEL_INFO, msg, True) + + @staticmethod + def scroll_to_top_left(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj to the top left.""" + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.TOP_LEFT, start_offset, end_offset) + + @staticmethod + def scroll_to_left_edge(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj to the left edge.""" + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.LEFT_EDGE, start_offset, end_offset) + + @staticmethod + def scroll_to_bottom_edge(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj to the bottom edge.""" + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.BOTTOM_EDGE, start_offset, end_offset) + + @staticmethod + def scroll_to_bottom_right(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj to the bottom right.""" + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.BOTTOM_RIGHT, start_offset, end_offset) + + @staticmethod + def scroll_to_right_edge(obj, start_offset=None, end_offset=None): + """Attempts to scroll obj to the right edge.""" + + AXEventSynthesizer._scroll_to_location( + obj, Atspi.ScrollType.RIGHT_EDGE, start_offset, end_offset) + + @staticmethod + def try_all_clickable_actions(obj): + """Attempts to perform a click-like action if one is available.""" + + actions = ["click", "press", "jump", "open"] + for action in actions: + if AXObject.do_named_action(obj, action): + tokens = ["AXEventSynthesizer: '", action, "' on", obj, "performed successfully"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if debug.LEVEL_INFO < debug.debugLevel: + return False + + tokens = ["AXEventSynthesizer: Actions on", obj, ":", AXObject.actions_as_string(obj)] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + +_synthesizer = AXEventSynthesizer() +def getSynthesizer(): + return _synthesizer diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_object.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_object.py new file mode 100644 index 0000000..d28aa17 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_object.py @@ -0,0 +1,1381 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for obtaining information about accessible objects. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import re +import threading +import time + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug + + +class AXObject: + """Utilities for obtaining information about accessible objects.""" + + KNOWN_DEAD = {} + REAL_APP_FOR_MUTTER_FRAME = {} + REAL_FRAME_FOR_MUTTER_FRAME = {} + + _lock = threading.Lock() + + @staticmethod + def _clear_stored_data(): + """Clears any data we have cached for objects""" + + while True: + time.sleep(60) + AXObject._clear_all_dictionaries() + + @staticmethod + def _clear_all_dictionaries(reason=""): + msg = "AXObject: Clearing cache." + if reason: + msg += f" Reason: {reason}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + with AXObject._lock: + tokens = ["AXObject: Clearing known dead-or-alive state for", + len(AXObject.KNOWN_DEAD), "objects"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + AXObject.KNOWN_DEAD.clear() + + tokens = ["AXObject: Clearing", len(AXObject.REAL_APP_FOR_MUTTER_FRAME), + "real apps for mutter frames"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + AXObject.REAL_APP_FOR_MUTTER_FRAME.clear() + + tokens = ["AXObject: Clearing", len(AXObject.REAL_FRAME_FOR_MUTTER_FRAME), + "real frames for mutter frames"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + AXObject.REAL_FRAME_FOR_MUTTER_FRAME.clear() + + @staticmethod + def clear_cache_now(reason=""): + """Clears all cached information immediately.""" + + AXObject._clear_all_dictionaries(reason) + + @staticmethod + def start_cache_clearing_thread(): + """Starts thread to periodically clear cached details.""" + + thread = threading.Thread(target=AXObject._clear_stored_data) + thread.daemon = True + thread.start() + + @staticmethod + def is_valid(obj): + """Returns False if we know for certain this object is invalid""" + + return not (obj is None or AXObject.object_is_known_dead(obj)) + + @staticmethod + def object_is_known_dead(obj): + """Returns True if we know for certain this object no longer exists""" + + return obj and AXObject.KNOWN_DEAD.get(hash(obj)) is True + + @staticmethod + def _set_known_dead_status(obj, is_dead): + """Updates the known-dead status of obj""" + + if obj is None: + return + + current_status = AXObject.KNOWN_DEAD.get(hash(obj)) + if current_status == is_dead: + return + + AXObject.KNOWN_DEAD[hash(obj)] = is_dead + if is_dead: + msg = "AXObject: Adding to known dead objects" + debug.printMessage(debug.LEVEL_INFO, msg, True, True) + return + + if current_status: + tokens = ["AXObject: Removing", obj, "from known-dead objects"] + debug.printTokens(debug.LEVEL_INFO, msg, tokens, True) + + @staticmethod + def handle_error(obj, error, msg): + """Parses the exception and potentially updates our status for obj""" + + error = str(error) + if re.search(r"accessible/\d+ does not exist", error): + msg = msg.replace(error, "object no longer exists") + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif re.search(r"The application no longer exists", error): + msg = msg.replace(error, "app no longer exists") + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if AXObject.KNOWN_DEAD.get(hash(obj)) is False: + AXObject._set_known_dead_status(obj, True) + + @staticmethod + def supports_action(obj): + """Returns True if the action interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_action_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_action_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_collection(obj): + """Returns True if the collection interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + app_name = AXObject.get_name(AXObject.get_application(obj)) + if app_name in ["soffice"]: + tokens = ["AXObject: Treating", app_name, "as not supporting collection."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + try: + iface = Atspi.Accessible.get_collection_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_collection_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_component(obj): + """Returns True if the component interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_component_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_component_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + + @staticmethod + def supports_document(obj): + """Returns True if the document interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_document_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_document_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_editable_text(obj): + """Returns True if the editable-text interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_editable_text_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_editable_text_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_hyperlink(obj): + """Returns True if the hyperlink interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_hyperlink(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_hyperlink on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_hypertext(obj): + """Returns True if the hypertext interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_hypertext_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_hypertext_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_image(obj): + """Returns True if the image interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_image_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_image_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_selection(obj): + """Returns True if the selection interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_selection_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_selection_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_table(obj): + """Returns True if the table interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_table_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_table_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_table_cell(obj): + """Returns True if the table cell interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_table_cell(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_table_cell on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supports_text(obj): + """Returns True if the text interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_text_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_text_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + return iface is not None + + @staticmethod + def supports_value(obj): + """Returns True if the value interface is supported on obj""" + + if not AXObject.is_valid(obj): + return False + + try: + iface = Atspi.Accessible.get_value_iface(obj) + except Exception as error: + msg = f"AXObject: Exception calling get_value_iface on {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return iface is not None + + @staticmethod + def supported_interfaces_as_string(obj): + """Returns the supported interfaces of obj as a string""" + + if not AXObject.is_valid(obj): + return "" + + iface_checks = [ + (AXObject.supports_action, "Action"), + (AXObject.supports_collection, "Collection"), + (AXObject.supports_component, "Component"), + (AXObject.supports_document, "Document"), + (AXObject.supports_editable_text, "EditableText"), + (AXObject.supports_hyperlink, "Hyperlink"), + (AXObject.supports_hypertext, "Hypertext"), + (AXObject.supports_image, "Image"), + (AXObject.supports_selection, "Selection"), + (AXObject.supports_table, "Table"), + (AXObject.supports_table_cell, "TableCell"), + (AXObject.supports_text, "Text"), + (AXObject.supports_value, "Value"), + ] + + ifaces = [iface for check, iface in iface_checks if check(obj)] + return ", ".join(ifaces) + + @staticmethod + def get_path(obj): + """Returns the path from application to obj as list of child indices""" + + if not AXObject.is_valid(obj): + return [] + + path = [] + acc = obj + while acc: + try: + path.append(Atspi.Accessible.get_index_in_parent(acc)) + except Exception as error: + msg = f"AXObject: Exception getting index in parent for {acc}: {error}" + AXObject.handle_error(acc, error, msg) + return [] + acc = AXObject.get_parent_checked(acc) + + path.reverse() + return path + + @staticmethod + def get_index_in_parent(obj): + """Returns the child index of obj within its parent""" + + if not AXObject.is_valid(obj): + return -1 + + try: + index = Atspi.Accessible.get_index_in_parent(obj) + except Exception as error: + msg = f"AXObject: Exception in get_index_in_parent: {error}" + AXObject.handle_error(obj, error, msg) + return -1 + + return index + + @staticmethod + def get_parent(obj): + """Returns the accessible parent of obj. See also get_parent_checked.""" + + if not AXObject.is_valid(obj): + return None + + try: + parent = Atspi.Accessible.get_parent(obj) + except Exception as error: + msg = f"AXObject: Exception in get_parent: {error}" + AXObject.handle_error(obj, error, msg) + return None + + if parent == obj: + tokens = ["AXObject:", obj, "claims to be its own parent"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return parent + + @staticmethod + def get_parent_checked(obj): + """Returns the parent of obj, doing checks for tree validity""" + + if not AXObject.is_valid(obj): + return None + + role = AXObject.get_role(obj) + if role in [Atspi.Role.INVALID, Atspi.Role.APPLICATION]: + return None + + parent = AXObject.get_parent(obj) + if parent is None: + return None + + if debug.LEVEL_INFO < debug.debugLevel: + return parent + + if AXObject.is_dead(obj): + return parent + + index = AXObject.get_index_in_parent(obj) + n_children = AXObject.get_child_count(parent) + if index < 0 or index >= n_children: + tokens = ["AXObject:", obj, "has index", index, + "; parent", parent, "has", n_children, "children"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return parent + + # This performs our check and includes any errors. We don't need the return value here. + AXObject.get_active_descendant_checked(parent, obj) + return parent + + @staticmethod + def find_ancestor(obj, pred): + """Returns the ancestor of obj if the function pred is true""" + + if not AXObject.is_valid(obj): + return None + + # Keep track of objects we've encountered in order to handle broken trees. + objects = [obj] + parent = AXObject.get_parent_checked(obj) + while parent: + if parent in objects: + tokens = ["AXObject: Circular tree suspected in find_ancestor. ", + parent, "already in: ", objects] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if pred(parent): + return parent + + objects.append(parent) + parent = AXObject.get_parent_checked(parent) + + return None + + @staticmethod + def is_ancestor(obj, ancestor): + """Returns true if ancestor is an ancestor of obj""" + + if not AXObject.is_valid(obj): + return False + + if not AXObject.is_valid(ancestor): + return False + + return AXObject.find_ancestor(obj, lambda x: x == ancestor) is not None + + @staticmethod + def get_child(obj, index): + """Returns the nth child of obj. See also get_child_checked.""" + + if not AXObject.is_valid(obj): + return None + + n_children = AXObject.get_child_count(obj) + if n_children <= 0: + return None + + if index == -1: + index = n_children - 1 + + if not 0 <= index < n_children: + return None + + try: + child = Atspi.Accessible.get_child_at_index(obj, index) + except Exception as error: + msg = f"AXObject: Exception in get_child: {error}" + AXObject.handle_error(obj, error, msg) + return None + + if child == obj: + tokens = ["AXObject:", obj, "claims to be its own child"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return child + + @staticmethod + def get_child_checked(obj, index): + """Returns the nth child of obj, doing checks for tree validity""" + + if not AXObject.is_valid(obj): + return None + + child = AXObject.get_child(obj, index) + if debug.LEVEL_INFO < debug.debugLevel: + return child + + parent = AXObject.get_parent(child) + if obj != parent: + tokens = ["AXObject:", obj, "claims", child, "as child; child's parent is", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return child + + @staticmethod + def get_active_descendant_checked(container, reported_child): + """Checks the reported active descendant and return the real/valid one.""" + + if not AXObject.has_state(container, Atspi.StateType.MANAGES_DESCENDANTS): + return reported_child + + index = AXObject.get_index_in_parent(reported_child) + try: + real_child = Atspi.Accessible.get_child_at_index(container, index) + except Exception as error: + msg = f"AXObject: Exception in get_active_descendant_checked: {error}" + AXObject.handle_error(container, error, msg) + return reported_child + + if real_child != reported_child: + tokens = ["AXObject: ", container, f"'s child at {index} is ", real_child, + "; not reported child", reported_child] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return real_child + + @staticmethod + def _find_descendant(obj, pred): + """Returns the descendant of obj if the function pred is true""" + + if not AXObject.is_valid(obj): + return None + + for i in range(AXObject.get_child_count(obj)): + child = AXObject.get_child_checked(obj, i) + if child and pred(child): + return child + + child = AXObject._find_descendant(child, pred) + if child and pred(child): + return child + + return None + + @staticmethod + def find_descendant(obj, pred): + """Returns the descendant of obj if the function pred is true""" + + start = time.time() + result = AXObject._find_descendant(obj, pred) + tokens = ["AXObject: find_descendant: found", result, f"in {time.time() - start:.4f}s"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + @staticmethod + def find_deepest_descendant(obj): + """Returns the deepest descendant of obj""" + + if not AXObject.is_valid(obj): + return None + + last_child = AXObject.get_child(obj, AXObject.get_child_count(obj) - 1) + if last_child is None: + return obj + + return AXObject.find_deepest_descendant(last_child) + + @staticmethod + def _find_all_descendants(obj, include_if, exclude_if, matches): + """Returns all descendants which match the specified inclusion and exclusion""" + + if not AXObject.is_valid(obj): + return + + child_count = AXObject.get_child_count(obj) + for i in range(child_count): + child = AXObject.get_child(obj, i) + if exclude_if and exclude_if(child): + continue + if include_if and include_if(child): + matches.append(child) + AXObject._find_all_descendants(child, include_if, exclude_if, matches) + + @staticmethod + def find_all_descendants(root, include_if=None, exclude_if=None): + """Returns all descendants which match the specified inclusion and exclusion""" + + start = time.time() + matches = [] + AXObject._find_all_descendants(root, include_if, exclude_if, matches) + msg = ( + f"AXObject: find_all_descendants: {len(matches)} " + f"matches found in {time.time() - start:.4f}s" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return matches + + @staticmethod + def get_role(obj): + """Returns the accessible role of obj""" + + if not AXObject.is_valid(obj): + return Atspi.Role.INVALID + + try: + role = Atspi.Accessible.get_role(obj) + except Exception as error: + msg = f"AXObject: Exception in get_role: {error}" + AXObject.handle_error(obj, error, msg) + return Atspi.Role.INVALID + + AXObject._set_known_dead_status(obj, False) + return role + + @staticmethod + def get_role_name(obj): + """Returns the accessible role name of obj""" + + if not AXObject.is_valid(obj): + return "" + + try: + role_name = Atspi.Accessible.get_role_name(obj) + except Exception as error: + msg = f"AXObject: Exception in get_role_name: {error}" + AXObject.handle_error(obj, error, msg) + return "" + + return role_name + + @staticmethod + def get_name(obj): + """Returns the accessible name of obj""" + + if not AXObject.is_valid(obj): + return "" + + try: + name = Atspi.Accessible.get_name(obj) + except Exception as error: + msg = f"AXObject: Exception in get_name: {error}" + AXObject.handle_error(obj, error, msg) + return "" + + AXObject._set_known_dead_status(obj, False) + return name + + @staticmethod + def has_same_non_empty_name(obj1, obj2): + """Returns true if obj1 and obj2 share the same non-empty name""" + + name1 = AXObject.get_name(obj1) + if not name1: + return False + + return name1 == AXObject.get_name(obj2) + + @staticmethod + def get_description(obj): + """Returns the accessible description of obj""" + + if not AXObject.is_valid(obj): + return "" + + try: + description = Atspi.Accessible.get_description(obj) + except Exception as error: + msg = f"AXObject: Exception in get_description: {error}" + AXObject.handle_error(obj, error, msg) + return "" + + return description + + @staticmethod + def get_child_count(obj): + """Returns the child count of obj""" + + if not AXObject.is_valid(obj): + return 0 + + try: + count = Atspi.Accessible.get_child_count(obj) + except Exception as error: + msg = f"AXObject: Exception in get_child_count: {error}" + AXObject.handle_error(obj, error, msg) + return 0 + + return count + + @staticmethod + def iter_children(obj, pred=None): + """Generator to iterate through obj's children. If the function pred is + specified, children for which pred is False will be skipped.""" + + if not AXObject.is_valid(obj): + return + + child_count = AXObject.get_child_count(obj) + for index in range(child_count): + child = AXObject.get_child(obj, index) + if child is not None and (pred is None or pred(child)): + yield child + + @staticmethod + def get_previous_sibling(obj): + """Returns the previous sibling of obj, based on child indices""" + + if not AXObject.is_valid(obj): + return None + + parent = AXObject.get_parent(obj) + if parent is None: + return None + + index = AXObject.get_index_in_parent(obj) + if index <= 0: + return None + + sibling = AXObject.get_child(parent, index - 1) + if sibling == obj: + tokens = ["AXObject:", obj, "claims to be its own sibling"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return sibling + + @staticmethod + def get_next_sibling(obj): + """Returns the next sibling of obj, based on child indices""" + + if not AXObject.is_valid(obj): + return None + + parent = AXObject.get_parent(obj) + if parent is None: + return None + + index = AXObject.get_index_in_parent(obj) + if index < 0: + return None + + sibling = AXObject.get_child(parent, index + 1) + if sibling == obj: + tokens = ["AXObject:", obj, "claims to be its own sibling"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return sibling + + @staticmethod + def get_next_object(obj): + """Returns the next object (depth first) in the accessibility tree""" + + if not AXObject.is_valid(obj): + return None + + index = AXObject.get_index_in_parent(obj) + 1 + parent = AXObject.get_parent(obj) + while parent and not 0 < index < AXObject.get_child_count(parent): + obj = parent + index = AXObject.get_index_in_parent(obj) + 1 + parent = AXObject.get_parent(obj) + + if parent is None: + return None + + next_object = AXObject.get_child(parent, index) + if next_object == obj: + tokens = ["AXObject:", obj, "claims to be its own next object"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return next_object + + @staticmethod + def get_previous_object(obj): + """Returns the previous object (depth first) in the accessibility tree""" + + if not AXObject.is_valid(obj): + return None + + index = AXObject.get_index_in_parent(obj) - 1 + parent = AXObject.get_parent(obj) + while parent and not 0 <= index < AXObject.get_child_count(parent) - 1: + obj = parent + index = AXObject.get_index_in_parent(obj) - 1 + parent = AXObject.get_parent(obj) + + if parent is None: + return None + + previous_object = AXObject.get_child(parent, index) + if previous_object == obj: + tokens = ["AXObject:", obj, "claims to be its own previous object"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return previous_object + + @staticmethod + def get_state_set(obj): + """Returns the state set associated with obj""" + + if not AXObject.is_valid(obj): + return Atspi.StateSet() + + try: + state_set = Atspi.Accessible.get_state_set(obj) + except Exception as error: + msg = f"AXObject: Exception in get_state_set: {error}" + AXObject.handle_error(obj, error, msg) + return Atspi.StateSet() + + AXObject._set_known_dead_status(obj, False) + return state_set + + @staticmethod + def has_state(obj, state): + """Returns true if obj has the specified state""" + + if not AXObject.is_valid(obj): + return False + + return AXObject.get_state_set(obj).contains(state) + + @staticmethod + def state_set_as_string(obj): + """Returns the state set associated with obj as a string""" + + if not AXObject.is_valid(obj): + return "" + + def as_string(state): + return state.value_name[12:].replace("_", "-").lower() + + return ", ".join(map(as_string, AXObject.get_state_set(obj).get_states())) + + @staticmethod + def get_relations(obj): + """Returns the list of Atspi.Relation objects associated with obj""" + + if not AXObject.is_valid(obj): + return [] + + try: + relations = Atspi.Accessible.get_relation_set(obj) + except Exception as error: + msg = f"AXObject: Exception in get_relations: {error}" + AXObject.handle_error(obj, error, msg) + return [] + + return relations + + @staticmethod + def get_relation(obj, relation_type): + """Returns the specified Atspi.Relation for obj""" + + if not AXObject.is_valid(obj): + return None + + for relation in AXObject.get_relations(obj): + if relation and relation.get_relation_type() == relation_type: + return relation + + return None + + @staticmethod + def has_relation(obj, relation_type): + """Returns true if obj has the specified relation type""" + + if not AXObject.is_valid(obj): + return False + + return AXObject.get_relation(obj, relation_type) is not None + + @staticmethod + def get_relation_targets(obj, relation_type, pred=None): + """Returns the list of targets with the specified relation type to obj. + If pred is provided, a target will only be included if pred is true.""" + + if not AXObject.is_valid(obj): + return [] + + relation = AXObject.get_relation(obj, relation_type) + if relation is None: + return [] + + targets = set() + for i in range(relation.get_n_targets()): + target = relation.get_target(i) + if pred is None or pred(target): + targets.add(target) + + # We want to avoid self-referential relationships. + type_includes_object = [Atspi.RelationType.MEMBER_OF] + if relation_type not in type_includes_object and obj in targets: + tokens = ["AXObject: ", obj, "is in its own", relation_type, "target list"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + targets.remove(obj) + + return list(targets) + + @staticmethod + def relations_as_string(obj): + """Returns the relations associated with obj as a string""" + + if not AXObject.is_valid(obj): + return "" + + def as_string(relations): + return relations.value_name[15:].replace("_", "-").lower() + + results = [] + for rel in AXObject.get_relations(obj): + type_string = as_string(rel.get_relation_type()) + targets = AXObject.get_relation_targets(obj, rel.get_relation_type()) + target_string = ",".join(map(str, targets)) + results.append(f"{type_string}: {target_string}") + + return "; ".join(results) + + + @staticmethod + def find_real_app_and_window_for(obj, app=None): + """Work around for window events coming from mutter-x11-frames.""" + + if app is None: + try: + app = Atspi.Accessible.get_application(obj) + except Exception as error: + msg = f"AXObject: Exception getting application of {obj}: {error}" + AXObject.handle_error(obj, error, msg) + return None, None + + if AXObject.get_name(app) != "mutter-x11-frames": + return app, obj + + real_app = AXObject.REAL_APP_FOR_MUTTER_FRAME.get(hash(obj)) + real_frame = AXObject.REAL_FRAME_FOR_MUTTER_FRAME.get(hash(obj)) + if real_app is not None and real_frame is not None: + return real_app, real_frame + + tokens = ["AXObject:", app, "is not valid app for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + try: + desktop = Atspi.get_desktop(0) + except Exception as error: + tokens = ["AXObject: Exception getting desktop from Atspi:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None, None + + name = AXObject.get_name(obj) + for desktop_app in AXObject.iter_children(desktop): + if AXObject.get_name(desktop_app) == "mutter-x11-frames": + continue + for frame in AXObject.iter_children(desktop_app): + if name == AXObject.get_name(frame): + real_app = desktop_app + real_frame = frame + + tokens = ["AXObject:", real_app, "is real app for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if real_frame != obj: + msg = "AXObject: Updated frame to frame from real app" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + AXObject.REAL_APP_FOR_MUTTER_FRAME[hash(obj)] = real_app + AXObject.REAL_FRAME_FOR_MUTTER_FRAME[hash(obj)] = real_frame + return real_app, real_frame + + @staticmethod + def get_application(obj): + """Returns the accessible application associated with obj""" + + if not AXObject.is_valid(obj): + return None + + app = AXObject.REAL_APP_FOR_MUTTER_FRAME.get(hash(obj)) + if app is not None: + return app + + try: + app = Atspi.Accessible.get_application(obj) + except Exception as error: + msg = f"AXObject: Exception in get_application: {error}" + AXObject.handle_error(obj, error, msg) + return None + + if AXObject.get_name(app) != "mutter-x11-frames": + return app + + real_app = AXObject.find_real_app_and_window_for(obj, app)[0] + if real_app is not None: + app = real_app + + return app + + @staticmethod + def get_application_toolkit_name(obj): + """Returns the toolkit name reported for obj's application.""" + + if not AXObject.is_valid(obj): + return "" + + app = AXObject.get_application(obj) + if app is None: + return "" + + try: + name = Atspi.Accessible.get_toolkit_name(app) + except Exception as error: + tokens = ["AXObject: Exception in get_application_toolkit_name:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + + return name + + @staticmethod + def get_application_toolkit_version(obj): + """Returns the toolkit version reported for obj's application.""" + + if not AXObject.is_valid(obj): + return "" + + app = AXObject.get_application(obj) + if app is None: + return "" + + try: + version = Atspi.Accessible.get_toolkit_version(app) + except Exception as error: + tokens = ["AXObject: Exception in get_application_toolkit_version:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + + return version + + @staticmethod + def application_as_string(obj): + """Returns the application details of obj as a string.""" + + if not AXObject.is_valid(obj): + return "" + + app = AXObject.get_application(obj) + if app is None: + return "" + + string = ( + f"{AXObject.get_name(app)} " + f"({AXObject.get_application_toolkit_name(obj)} " + f"{AXObject.get_application_toolkit_version(obj)})" + ) + return string + + @staticmethod + def clear_cache(obj, recursive=False): + """Clears the Atspi cached information associated with obj""" + + if not AXObject.is_valid(obj): + return + + if not recursive: + try: + Atspi.Accessible.clear_cache_single(obj) + except Exception: + # This is new API, added in 2.49.1. So log success rather than + # (likely) failure for now. + pass + else: + msg = "AXObject: clear_cache_single succeeded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + try: + Atspi.Accessible.clear_cache(obj) + except Exception as error: + msg = f"AXObject: Exception in clear_cache: {error}" + AXObject.handle_error(obj, error, msg) + + @staticmethod + def get_process_id(obj): + """Returns the process id associated with obj""" + + if not AXObject.is_valid(obj): + return -1 + + try: + pid = Atspi.Accessible.get_process_id(obj) + except Exception as error: + msg = f"AXObject: Exception in get_process_id: {error}" + AXObject.handle_error(obj, error, msg) + return -1 + + return pid + + @staticmethod + def is_dead(obj): + """Returns true of obj exists but is believed to be dead.""" + + if obj is None: + return False + + if not AXObject.is_valid(obj): + return True + + try: + # We use the Atspi function rather than the AXObject function because the + # latter intentionally handles exceptions. + Atspi.Accessible.get_name(obj) + except Exception as error: + msg = f"AXObject: Accessible is dead: {error}" + AXObject.handle_error(obj, error, msg) + return True + + AXObject._set_known_dead_status(obj, False) + return False + + @staticmethod + def get_attributes_dict(obj): + """Returns the object attributes of obj as a dictionary.""" + + if not AXObject.is_valid(obj): + return {} + + try: + attributes = Atspi.Accessible.get_attributes(obj) + except Exception as error: + msg = f"AXObject: Exception in get_attributes_dict: {error}" + AXObject.handle_error(obj, error, msg) + return {} + + if attributes is None: + return {} + + return attributes + + @staticmethod + def get_attribute(obj, attribute_name): + """Returns the value of the specified attribute as a string.""" + + if not AXObject.is_valid(obj): + return "" + + attributes = AXObject.get_attributes_dict(obj) + return attributes.get(attribute_name, "") + + @staticmethod + def attributes_as_string(obj): + """Returns the object attributes of obj as a string.""" + + if not AXObject.is_valid(obj): + return "" + + def as_string(attribute): + return f"{attribute[0]}:{attribute[1]}" + + return ", ".join(map(as_string, AXObject.get_attributes_dict(obj).items())) + + @staticmethod + def get_n_actions(obj): + """Returns the number of actions supported on obj.""" + + if not AXObject.supports_action(obj): + return 0 + + try: + count = Atspi.Action.get_n_actions(obj) + except Exception as error: + msg = f"AXObject: Exception in get_n_actions: {error}" + AXObject.handle_error(obj, error, msg) + return 0 + + return count + + @staticmethod + def _normalize_action_name(action_name): + """Adjusts the name to account for differences in implementations.""" + + if not action_name: + return "" + + name = re.sub(r'(?<=[a-z])([A-Z])', r'-\1', action_name).lower() + name = re.sub('[!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]', '-', name) + return name + + @staticmethod + def get_action_name(obj, i): + """Returns the name of obj's action at index i.""" + + if not 0 <= i < AXObject.get_n_actions(obj): + return "" + + try: + name = Atspi.Action.get_action_name(obj, i) + except Exception as error: + msg = f"AXObject: Exception in get_action_name: {error}" + AXObject.handle_error(obj, error, msg) + return "" + + return AXObject._normalize_action_name(name) + + @staticmethod + def get_action_names(obj): + """Returns the list of actions supported on obj.""" + + results = [] + for i in range(AXObject.get_n_actions(obj)): + name = AXObject.get_action_name(obj, i) + if name: + results.append(name) + return results + + @staticmethod + def get_action_description(obj, i): + """Returns the description of obj's action at index i.""" + + if not 0 <= i < AXObject.get_n_actions(obj): + return "" + + try: + description = Atspi.Action.get_action_description(obj, i) + except Exception as error: + msg = f"AXObject: Exception in get_action_description: {error}" + AXObject.handle_error(obj, error, msg) + return "" + + return description + + @staticmethod + def get_action_key_binding(obj, i): + """Returns the key binding string of obj's action at index i.""" + + if not 0 <= i < AXObject.get_n_actions(obj): + return "" + + try: + keybinding = Atspi.Action.get_key_binding(obj, i) + except Exception as error: + msg = f"AXObject: Exception in get_action_key_binding: {error}" + AXObject.handle_error(obj, error, msg) + return "" + + return keybinding + + @staticmethod + def has_action(obj, action_name): + """Returns true if the named action is supported on obj.""" + + return AXObject.get_action_index(obj, action_name) >= 0 + + @staticmethod + def get_action_index(obj, action_name): + """Returns the index of the named action or -1 if unsupported.""" + + action_name = AXObject._normalize_action_name(action_name) + for i in range(AXObject.get_n_actions(obj)): + if action_name == AXObject.get_action_name(obj, i): + return i + + return -1 + + @staticmethod + def do_action(obj, i): + """Invokes obj's action at index i. The return value, if true, may be + meaningless because most implementors return true without knowing if + the action was successfully performed.""" + + if not 0 <= i < AXObject.get_n_actions(obj): + return False + + try: + result = Atspi.Action.do_action(obj, i) + except Exception as error: + msg = f"AXObject: Exception in do_action: {error}" + AXObject.handle_error(obj, error, msg) + return False + + return result + + @staticmethod + def do_named_action(obj, action_name): + """Invokes the named action on obj. The return value, if true, may be + meaningless because most implementors return true without knowing if + the action was successfully performed.""" + + index = AXObject.get_action_index(obj, action_name) + if index == -1: + tokens = ["INFO:", action_name, "not an available action for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return AXObject.do_action(obj, index) + + @staticmethod + def actions_as_string(obj): + """Returns information about the actions as a string.""" + + results = [] + for i in range(AXObject.get_n_actions(obj)): + result = AXObject.get_action_name(obj, i) + keybinding = AXObject.get_action_key_binding(obj, i) + if keybinding: + result += f" ({keybinding})" + results.append(result) + + return "; ".join(results) + +AXObject.start_cache_clearing_thread() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_selection.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_selection.py new file mode 100644 index 0000000..6926699 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_selection.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for obtaining information about containers supporting selection. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import gi + +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from .ax_object import AXObject + + +class AXSelection: + """Utilities for obtaining information about containers supporting selection.""" + + @staticmethod + def get_selected_child_count(obj): + """Returns the selected child count of obj""" + + if not AXObject.supports_selection(obj): + return 0 + + try: + count = Atspi.Selection.get_n_selected_children(obj) + except Exception as error: + tokens = ["AXSelection: Exception in get_selected_child_count:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return 0 + + tokens = ["AXSelection:", obj, "reports", count, "selected children"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return count + + @staticmethod + def get_selected_child(obj, index): + """Returns the nth selected child of obj.""" + + n_children = AXSelection.get_selected_child_count(obj) + if n_children <= 0: + return None + + if index == -1: + index = n_children - 1 + + if not 0 <= index < n_children: + return None + + try: + child = Atspi.Selection.get_selected_child(obj, index) + except Exception as error: + tokens = ["AXSelection: Exception in get_selected_child:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if child == obj: + tokens = ["AXSelection:", obj, "claims to be its own selected child"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + tokens = ["AXSelection:", child, "is selected child #", index, "of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return child + + @staticmethod + def get_selected_children(obj): + """Returns a list of all the selected children of obj.""" + + count = AXSelection.get_selected_child_count(obj) + children = set() + for i in range(count): + try: + child = Atspi.Selection.get_selected_child(obj, i) + except Exception as error: + tokens = ["AXSelection: Exception in get_selected_children:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + if child is not None: + children.add(child) + + if obj in children: + tokens = ["AXSelection:", obj, "claims to be its own selected child"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + children.remove(obj) + + result = list(children) + if len(result) != count: + tokens = ["AXSelection: Selected child count of", obj, f"is {count}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities.py new file mode 100644 index 0000000..aebc4f4 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for performing tasks related to accessibility inspection. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import inspect + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from .ax_object import AXObject +from .ax_utilities_collection import AXUtilitiesCollection +from .ax_utilities_role import AXUtilitiesRole +from .ax_utilities_state import AXUtilitiesState + + +class AXUtilities: + """Utilities for performing tasks related to accessibility inspection.""" + + COMPARE_COLLECTION_PERFORMANCE = False + + @staticmethod + def get_desktop(): + """Returns the accessible desktop""" + + try: + desktop = Atspi.get_desktop(0) + except Exception as error: + tokens = ["ERROR: Exception getting desktop from Atspi:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return desktop + + @staticmethod + def get_all_applications(must_have_window=False): + """Returns a list of running applications known to Atspi, filtering out + those which have no child windows if must_have_window is True.""" + + desktop = AXUtilities.get_desktop() + if desktop is None: + return [] + + def pred(obj): + if must_have_window: + return AXObject.get_child_count(obj) > 0 + return True + + return list(AXObject.iter_children(desktop, pred)) + + @staticmethod + def is_application_in_desktop(app): + """Returns true if app is known to Atspi""" + + desktop = AXUtilities.get_desktop() + if desktop is None: + return False + + for child in AXObject.iter_children(desktop): + if child == app: + return True + + tokens = ["WARNING:", app, "is not in", desktop] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + @staticmethod + def get_application_with_pid(pid): + """Returns the accessible application with the specified pid""" + + desktop = AXUtilities.get_desktop() + if desktop is None: + return None + + for app in AXObject.iter_children(desktop): + if AXObject.get_process_id(app) == pid: + return app + + tokens = ["WARNING: app with pid", pid, "is not in", desktop] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + @staticmethod + def get_all_static_text_leaf_nodes(obj): + """Returns all the descendants of obj that are static text leaf nodes""" + + roles = [Atspi.Role.STATIC, Atspi.Role.TEXT] + def is_not_element(acc): + return AXObject.get_attribute(acc, "tag") in (None, "", "br") + + result = None + if AXObject.supports_collection(obj): + result = AXUtilitiesCollection.find_all_with_role(obj, roles, is_not_element) + if not AXUtilities.COMPARE_COLLECTION_PERFORMANCE: + return result + + def is_match(acc): + return AXObject.get_role(acc) in roles and is_not_element(acc) + + return AXObject.find_all_descendants(obj, is_match) + + @staticmethod + def get_all_widgets(obj, must_be_showing_and_visible=True): + """Returns all the descendants of obj with a widget role""" + + roles = AXUtilitiesRole.get_widget_roles() + result = None + if AXObject.supports_collection(obj): + if not must_be_showing_and_visible: + result = AXUtilitiesCollection.find_all_with_role(obj, roles) + else: + states = [Atspi.StateType.SHOWING, Atspi.StateType.VISIBLE] + result = AXUtilitiesCollection.find_all_with_role_and_all_states( + obj, roles, states) + + if not AXUtilities.COMPARE_COLLECTION_PERFORMANCE: + return result + + def is_match(acc): + if AXObject.get_role(acc) not in roles: + return False + if must_be_showing_and_visible: + return AXUtilitiesState.is_showing(acc) and AXUtilitiesState.is_visible(acc) + return True + + return AXObject.find_all_descendants(obj, is_match) + + @staticmethod + def get_default_button(obj): + """Returns the default button descendant of obj""" + + result = None + if AXObject.supports_collection(obj): + result = AXUtilitiesCollection.find_default_button(obj) + if not AXUtilities.COMPARE_COLLECTION_PERFORMANCE: + return result + + return AXObject.find_descendant(obj, AXUtilitiesRole.is_default_button) + + @staticmethod + def get_focused_object(obj): + """Returns the focused descendant of obj""" + + result = None + if AXObject.supports_collection(obj): + result = AXUtilitiesCollection.find_focused_object(obj) + if not AXUtilities.COMPARE_COLLECTION_PERFORMANCE: + return result + + return AXObject.find_descendant(obj, AXUtilitiesState.is_focused) + + @staticmethod + def get_status_bar(obj): + """Returns the status bar descendant of obj""" + + result = None + if AXObject.supports_collection(obj): + result = AXUtilitiesCollection.find_status_bar(obj) + if not AXUtilities.COMPARE_COLLECTION_PERFORMANCE: + return result + + return AXObject.find_descendant(obj, AXUtilitiesRole.is_status_bar) + + +for name, method in inspect.getmembers(AXUtilitiesRole, predicate=inspect.isfunction): + setattr(AXUtilities, name, method) + +for name, method in inspect.getmembers(AXUtilitiesState, predicate=inspect.isfunction): + setattr(AXUtilities, name, method) + +for name, method in inspect.getmembers(AXUtilitiesCollection, predicate=inspect.isfunction): + if name.startswith("find"): + setattr(AXUtilities, name, method) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_collection.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_collection.py new file mode 100644 index 0000000..7b44591 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_collection.py @@ -0,0 +1,1677 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for finding all objects that meet a certain criteria. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import inspect +import time + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from .ax_collection import AXCollection +from .ax_object import AXObject +from .ax_utilities_role import AXUtilitiesRole +from .ax_utilities_state import AXUtilitiesState + + +class AXUtilitiesCollection: + """Utilities for finding all objects that meet a certain criteria.""" + + @staticmethod + def _apply_predicate(matches, pred): + if not matches: + return [] + + start = time.time() + tokens = ["AXUtilitiesCollection: Applying predicate ", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + matches = list(filter(pred, matches)) + msg = f"AXUtilitiesCollection: {len(matches)} matches found in {time.time() - start:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return matches + + @staticmethod + def _find_all_with_states(root, state_list, state_match_type, pred=None): + if not (root and state_list): + return [] + + state_list = list(state_list) + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, state_match_type, "of:", state_list] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rule = AXCollection.create_match_rule(states=state_list, state_match_type=state_match_type) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def _find_all_with_role(root, role_list, role_match_type, pred=None): + if not (root and role_list): + return [] + + role_list = list(role_list) + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, role_match_type, "of:", role_list] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rule = AXCollection.create_match_rule(roles=role_list, role_match_type=role_match_type) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def find_all_with_interfaces(root, interface_list, pred=None): + """Returns all descendants of root which implement all the specified interfaces""" + + if not (root and interface_list): + return [] + + interface_list = list(interface_list) + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "all of:", interface_list] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rule = AXCollection.create_match_rule(interfaces=interface_list) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def find_all_with_role(root, role_list, pred=None): + """Returns all descendants of root with any of the specified roles""" + + return AXUtilitiesCollection._find_all_with_role( + root, role_list, Atspi.CollectionMatchType.ANY, pred) + + @staticmethod + def find_all_without_roles(root, role_list, pred=None): + """Returns all descendants of root which have none of the specified roles""" + + return AXUtilitiesCollection._find_all_with_role( + root, role_list, Atspi.CollectionMatchType.NONE, pred) + + @staticmethod + def find_all_with_role_and_all_states(root, role_list, state_list, pred=None): + """Returns all descendants of root with any of the roles, and all the states""" + + if not (root and role_list and state_list): + return [] + + role_list = list(role_list) + state_list = list(state_list) + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "Roles:", role_list, "States:", state_list] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rule = AXCollection.create_match_rule( + roles=role_list, states=state_list, state_match_type=Atspi.CollectionMatchType.ALL) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def find_all_with_role_and_any_state(root, role_list, state_list, pred=None): + """Returns all descendants of root with any of the roles, and any of the states""" + + if not (root and role_list and state_list): + return [] + + role_list = list(role_list) + state_list = list(state_list) + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "Roles:", role_list, "States:", state_list] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rule = AXCollection.create_match_rule( + roles=role_list, states=state_list, state_match_type=Atspi.CollectionMatchType.ANY) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def find_all_with_role_without_states(root, role_list, state_list, pred=None): + """Returns all descendants of root with any of the roles, and none of the states""" + + if not (root and role_list and state_list): + return [] + + role_list = list(role_list) + state_list = list(state_list) + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "Roles:", role_list, "States:", state_list] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rule = AXCollection.create_match_rule( + roles=role_list, states=state_list, state_match_type=Atspi.CollectionMatchType.NONE) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def find_all_with_states(root, state_list, pred=None): + """Returns all descendants of root which have all of the specified states""" + + return AXUtilitiesCollection._find_all_with_states( + root, state_list, Atspi.CollectionMatchType.ALL, pred) + + @staticmethod + def find_all_with_any_state(root, state_list, pred=None): + """Returns all descendants of root which have any of the specified states""" + + return AXUtilitiesCollection._find_all_with_states( + root, state_list, Atspi.CollectionMatchType.ANY, pred) + + @staticmethod + def find_all_without_states(root, state_list, pred=None): + """Returns all descendants of root which have none of the specified states""" + + return AXUtilitiesCollection._find_all_with_states( + root, state_list, Atspi.CollectionMatchType.NONE, pred) + + @staticmethod + def find_all_accelerator_labels(root, pred=None): + """Returns all descendants of root with the accelerator label role""" + + roles = [Atspi.Role.ACCELERATOR_LABEL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_alerts(root, pred=None): + """Returns all descendants of root with the alert role""" + + roles = [Atspi.Role.ALERT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_animations(root, pred=None): + """Returns all descendants of root with the animation role""" + + roles = [Atspi.Role.ANIMATION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_arrows(root, pred=None): + """Returns all descendants of root with the arrow role""" + + roles = [Atspi.Role.ARROW] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_articles(root, pred=None): + """Returns all descendants of root with the article role""" + + roles = [Atspi.Role.ARTICLE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_audios(root, pred=None): + """Returns all descendants of root with the audio role""" + + roles = [Atspi.Role.AUDIO] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_autocompletes(root, pred=None): + """Returns all descendants of root with the autocomplete role""" + + roles = [Atspi.Role.AUTOCOMPLETE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_block_quotes(root, pred=None): + """Returns all descendants of root with the block quote role""" + + roles = [Atspi.Role.BLOCK_QUOTE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_buttons(root, pred=None): + """Returns all descendants of root with the push- or toggle-button role""" + + roles = [Atspi.Role.PUSH_BUTTON, Atspi.Role.TOGGLE_BUTTON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_calendars(root, pred=None): + """Returns all descendants of root with the calendar role""" + + roles = [Atspi.Role.CALENDAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_canvases(root, pred=None): + """Returns all descendants of root with the canvas role""" + + roles = [Atspi.Role.CANVAS] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_captions(root, pred=None): + """Returns all descendants of root with the caption role""" + + roles = [Atspi.Role.CAPTION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_charts(root, pred=None): + """Returns all descendants of root with the chart role""" + + roles = [Atspi.Role.CHART] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_check_boxes(root, pred=None): + """Returns all descendants of root with the checkbox role""" + + roles = [Atspi.Role.CHECK_BOX] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_check_menu_items(root, pred=None): + """Returns all descendants of root with the check menuitem role""" + + roles = [Atspi.Role.CHECK_MENU_ITEM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_clickables(root, pred=None): + """Returns all non-focusable descendants of root which support the click action""" + + if root is None: + return [] + + interfaces = ["Action"] + states = [Atspi.StateType.FOCUSABLE] + state_match_type = Atspi.CollectionMatchType.NONE + roles = AXUtilitiesRole.get_roles_to_exclude_from_clickables_list() + roles_match_type = Atspi.CollectionMatchType.NONE + attributes = ["xml-roles:gridcell"] + attribute_match_type = Atspi.CollectionMatchType.NONE + + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, roles_match_type, "of:", roles, ". pred:", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def is_match(obj): + result = AXObject.has_action(obj, "click") + tokens = ["AXUtilitiesCollection:", obj, AXObject.actions_as_string(obj), + "has click Action:", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not result: + return False + return pred is None or pred(obj) + + rule = AXCollection.create_match_rule( + interfaces=interfaces, + attributes=attributes, + attribute_match_type=attribute_match_type, + roles=roles, + role_match_type=roles_match_type, + states=states, + state_match_type=state_match_type) + matches = AXCollection.get_all_matches(root, rule) + matches = AXUtilitiesCollection._apply_predicate(matches, is_match) + return matches + + @staticmethod + def find_all_color_choosers(root, pred=None): + """Returns all descendants of root with the color_chooser role""" + + roles = [Atspi.Role.COLOR_CHOOSER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_column_headers(root, pred=None): + """Returns all descendants of root with the column header role""" + + roles = [Atspi.Role.COLUMN_HEADER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_combo_boxes(root, pred=None): + """Returns all descendants of root with the combobox role""" + + roles = [Atspi.Role.COMBO_BOX] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_comments(root, pred=None): + """Returns all descendants of root with the comment role""" + + roles = [Atspi.Role.COMMENT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_content_deletions(root, pred=None): + """Returns all descendants of root with the content deletion role""" + + roles = [Atspi.Role.CONTENT_DELETION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_content_insertions(root, pred=None): + """Returns all descendants of root with the content insertion role""" + + roles = [Atspi.Role.CONTENT_INSERTION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_date_editors(root, pred=None): + """Returns all descendants of root with the date editor role""" + + roles = [Atspi.Role.DATE_EDITOR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_definitions(root, pred=None): + """Returns all descendants of root with the definition role""" + + roles = [Atspi.Role.DEFINITION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_description_lists(root, pred=None): + """Returns all descendants of root with the description list role""" + + roles = [Atspi.Role.DESCRIPTION_LIST] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_description_terms(root, pred=None): + """Returns all descendants of root with the description term role""" + + roles = [Atspi.Role.DESCRIPTION_TERM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_description_values(root, pred=None): + """Returns all descendants of root with the description value role""" + + roles = [Atspi.Role.DESCRIPTION_VALUE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_desktop_frames(root, pred=None): + """Returns all descendants of root with the desktop frame role""" + + roles = [Atspi.Role.DESKTOP_FRAME] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_desktop_icons(root, pred=None): + """Returns all descendants of root with the desktop icon role""" + + roles = [Atspi.Role.DESKTOP_ICON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_dials(root, pred=None): + """Returns all descendants of root with the dial role""" + + roles = [Atspi.Role.DIAL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_dialogs(root, pred=None): + """Returns all descendants of root with the dialog role""" + + roles = [Atspi.Role.DIALOG] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_dialogs_and_alerts(root, pred=None): + """Returns all descendants of root that has any dialog or alert role""" + + roles = AXUtilitiesRole.get_dialog_roles(True) + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_directory_panes(root, pred=None): + """Returns all descendants of root with the directory pane role""" + + roles = [Atspi.Role.DIRECTORY_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_documents(root, pred=None): + """Returns all descendants of root that has any document-related role""" + + roles = AXUtilitiesRole.get_document_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_document_emails(root, pred=None): + """Returns all descendants of root with the document email role""" + + roles = [Atspi.Role.DOCUMENT_EMAIL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_document_frames(root, pred=None): + """Returns all descendants of root with the document frame role""" + + roles = [Atspi.Role.DOCUMENT_FRAME] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_document_presentations(root, pred=None): + """Returns all descendants of root with the document presentation role""" + + roles = [Atspi.Role.DOCUMENT_PRESENTATION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_document_spreadsheets(root, pred=None): + """Returns all descendants of root with the document spreadsheet role""" + + roles = [Atspi.Role.DOCUMENT_SPREADSHEET] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_document_texts(root, pred=None): + """Returns all descendants of root with the document text role""" + + roles = [Atspi.Role.DOCUMENT_TEXT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_document_webs(root, pred=None): + """Returns all descendants of root with the document web role""" + + roles = [Atspi.Role.DOCUMENT_WEB] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_drawing_areas(root, pred=None): + """Returns all descendants of root with the drawing area role""" + + roles = [Atspi.Role.DRAWING_AREA] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_editable_objects(root, must_be_focusable=True, pred=None): + """Returns all descendants of root which are editable""" + + states = [Atspi.StateType.EDITABLE] + if must_be_focusable: + states.append(Atspi.StateType.FOCUSABLE) + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_editbars(root, pred=None): + """Returns all descendants of root with the editbar role""" + + roles = [Atspi.Role.EDITBAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_embeddeds(root, pred=None): + """Returns all descendants of root with the embedded role""" + + roles = [Atspi.Role.EMBEDDED] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_entries(root, pred=None): + """Returns all descendants of root with the entry role""" + + roles = [Atspi.Role.ENTRY] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_extendeds(root, pred=None): + """Returns all descendants of root with the extended role""" + + roles = [Atspi.Role.EXTENDED] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_file_choosers(root, pred=None): + """Returns all descendants of root with the file chooser role""" + + roles = [Atspi.Role.FILE_CHOOSER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_fillers(root, pred=None): + """Returns all descendants of root with the filler role""" + + roles = [Atspi.Role.FILLER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_focusable_objects(root, pred=None): + """Returns all descendants of root which are focusable""" + + states = [Atspi.StateType.FOCUSABLE] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_focusable_objects_with_click_ancestor(root, pred=None): + """Returns all focusable descendants of root which support the click-ancestor action""" + + if root is None: + return [] + + interfaces = ["Action"] + states = [Atspi.StateType.FOCUSABLE] + state_match_type = Atspi.CollectionMatchType.ANY + roles = AXUtilitiesRole.get_roles_to_exclude_from_clickables_list() + roles_match_type = Atspi.CollectionMatchType.NONE + + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, roles_match_type, "of:", roles, ". pred:", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def is_match(obj): + result = AXObject.has_action(obj, "click-ancestor") + tokens = ["AXUtilitiesCollection:", obj, AXObject.actions_as_string(obj), + "has click-ancestor Action:", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not result: + return False + return pred is None or pred(obj) + + rule = AXCollection.create_match_rule( + interfaces=interfaces, + roles=roles, + role_match_type=roles_match_type, + states=states, + state_match_type=state_match_type) + matches = AXCollection.get_all_matches(root, rule) + matches = AXUtilitiesCollection._apply_predicate(matches, is_match) + return matches + + @staticmethod + def find_all_focused_objects(root, pred=None): + """Returns all descendants of root which are focused""" + + states = [Atspi.StateType.FOCUSED] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_focus_traversables(root, pred=None): + """Returns all descendants of root with the focus traversable role""" + + roles = [Atspi.Role.FOCUS_TRAVERSABLE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_font_choosers(root, pred=None): + """Returns all descendants of root with the font chooser role""" + + roles = [Atspi.Role.FONT_CHOOSER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_footers(root, pred=None): + """Returns all descendants of root with the footer role""" + + roles = [Atspi.Role.FOOTER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_footnotes(root, pred=None): + """Returns all descendants of root with the footnote role""" + + roles = [Atspi.Role.FOOTNOTE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_forms(root, pred=None): + """Returns all descendants of root with the form role""" + + roles = [Atspi.Role.FORM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_form_fields(root, must_be_focusable=True, pred=None): + """Returns all descendants of root with a form-field-related role""" + + roles = AXUtilitiesRole.get_form_field_roles() + if not must_be_focusable: + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + states = [Atspi.StateType.FOCUSABLE] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_frames(root, pred=None): + """Returns all descendants of root with the frame role""" + + roles = [Atspi.Role.FRAME] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_glass_panes(root, pred=None): + """Returns all descendants of root with the glass pane role""" + + roles = [Atspi.Role.GLASS_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_grids(root, pred=None): + """Returns all descendants of root that are grids""" + + if root is None: + return [] + + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "pred:", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + roles = [Atspi.Role.TABLE] + attributes = ["xml-roles:grid"] + rule = AXCollection.create_match_rule(roles=roles, attributes=attributes) + grids = AXCollection.get_all_matches(root, rule) + if pred is not None: + AXUtilitiesCollection._apply_predicate(grids, pred) + + return grids + + @staticmethod + def find_all_grid_cells(root, pred=None): + """Returns all descendants of root that are grid cells""" + + if root is None: + return [] + + grids = AXUtilitiesCollection.find_all_grids(root, pred) + if not grids: + return [] + + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "pred:", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + cells = [] + for grid in grids: + cells.extend(AXUtilitiesCollection.find_all_table_cells(grid)) + + if pred is not None: + AXUtilitiesCollection._apply_predicate(cells, pred) + + return cells + + @staticmethod + def find_all_groupings(root, pred=None): + """Returns all descendants of root with the grouping role""" + + roles = [Atspi.Role.GROUPING] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_headers(root, pred=None): + """Returns all descendants of root with the header role""" + + roles = [Atspi.Role.HEADER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_headings(root, pred=None): + """Returns all descendants of root with the heading role""" + + roles = [Atspi.Role.HEADING] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_headings_at_level(root, level, pred=None): + """Returns all descendants of root with the heading role""" + + if root is None: + return [] + + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "Level:", level, "pred:", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + roles = [Atspi.Role.HEADING] + attributes = [f"level:{level}"] + rule = AXCollection.create_match_rule(roles=roles, attributes=attributes) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + return matches + + @staticmethod + def find_all_html_containers(root, pred=None): + """Returns all descendants of root with the html container role""" + + roles = [Atspi.Role.HTML_CONTAINER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_horizontal_scrollbars(root, pred=None): + """Returns all descendants of root that is a horizontal scrollbar""" + + roles = [Atspi.Role.SCROLL_BAR] + states = [Atspi.StateType.HORIZONTAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_horizontal_separators(root, pred=None): + """Returns all descendants of root that is a horizontal separator""" + + roles = [Atspi.Role.SEPARATOR] + states = [Atspi.StateType.HORIZONTAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_horizontal_sliders(root, pred=None): + """Returns all descendants of root that is a horizontal slider""" + + roles = [Atspi.Role.SLIDER] + states = [Atspi.StateType.HORIZONTAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_icons(root, pred=None): + """Returns all descendants of root with the icon role""" + + roles = [Atspi.Role.ICON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_icons_and_canvases(root, pred=None): + """Returns all descendants of root with the icon or canvas role""" + + roles = [Atspi.Role.ICON, Atspi.Role.CANVAS] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_images(root, pred=None): + """Returns all descendants of root with the image role""" + + roles = [Atspi.Role.IMAGE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_images_and_canvases(root, pred=None): + """Returns all descendants of root with the image or canvas role""" + + roles = [Atspi.Role.IMAGE, Atspi.Role.CANVAS] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_images_and_image_maps(root, pred=None): + """Returns all descendants of root with the image or image map role""" + + roles = [Atspi.Role.IMAGE, Atspi.Role.IMAGE_MAP] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_image_maps(root, pred=None): + """Returns all descendants of root with the image map role""" + + roles = [Atspi.Role.IMAGE_MAP] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_info_bars(root, pred=None): + """Returns all descendants of root with the info bar role""" + + roles = [Atspi.Role.INFO_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_input_method_windows(root, pred=None): + """Returns all descendants of root with the input method window role""" + + roles = [Atspi.Role.INPUT_METHOD_WINDOW] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_internal_frames(root, pred=None): + """Returns all descendants of root with the internal frame role""" + + roles = [Atspi.Role.INTERNAL_FRAME] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_labels(root, pred=None): + """Returns all descendants of root with the label role""" + + roles = [Atspi.Role.LABEL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_labels_and_captions(root, pred=None): + """Returns all descendants of root with the label or caption role""" + + roles = [Atspi.Role.LABEL, Atspi.Role.CAPTION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_landmarks(root, pred=None): + """Returns all descendants of root with the landmark role""" + + roles = [Atspi.Role.LANDMARK] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_layered_panes(root, pred=None): + """Returns all descendants of root with the layered pane role""" + + roles = [Atspi.Role.LAYERED_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_level_bars(root, pred=None): + """Returns all descendants of root with the level bar role""" + + roles = [Atspi.Role.LEVEL_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_links(root, must_be_focusable=True, pred=None): + """Returns all descendants of root with the link role""" + + roles = [Atspi.Role.LINK] + if not must_be_focusable: + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + states = [Atspi.StateType.FOCUSABLE] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_live_regions(root, pred=None): + """Returns all descendants of root that are live regions""" + + if root is None: + return [] + + tokens = ["AXUtilitiesCollection:", inspect.currentframe(), + "Root:", root, "pred:", pred] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + attributes = [] + levels = ["off", "polite", "assertive"] + for level in levels: + attributes.append('container-live:' + level) + + rule = AXCollection.create_match_rule(attributes=attributes) + matches = AXCollection.get_all_matches(root, rule) + if pred is not None: + matches = AXUtilitiesCollection._apply_predicate(matches, pred) + + return matches + + @staticmethod + def find_all_lists(root, pred=None): + """Returns all descendants of root with the list role""" + + roles = [Atspi.Role.LIST] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_list_boxes(root, pred=None): + """Returns all descendants of root with the list box role""" + + roles = [Atspi.Role.LIST_BOX] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_list_items(root, pred=None): + """Returns all descendants of root with the list item role""" + + roles = [Atspi.Role.LIST_ITEM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_logs(root, pred=None): + """Returns all descendants of root with the log role""" + + roles = [Atspi.Role.LOG] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_marks(root, pred=None): + """Returns all descendants of root with the mark role""" + + roles = [Atspi.Role.MARK] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_marquees(root, pred=None): + """Returns all descendants of root with the marquee role""" + + roles = [Atspi.Role.MARQUEE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_maths(root, pred=None): + """Returns all descendants of root with the math role""" + + roles = [Atspi.Role.MATH] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_math_fractions(root, pred=None): + """Returns all descendants of root with the math fraction role""" + + roles = [Atspi.Role.MATH_FRACTION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_math_roots(root, pred=None): + """Returns all descendants of root with the math root role""" + + roles = [Atspi.Role.MATH_ROOT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_menus(root, pred=None): + """Returns all descendants of root with the menu role""" + + roles = [Atspi.Role.MENU] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_menu_bars(root, pred=None): + """Returns all descendants of root with the menubar role""" + + roles = [Atspi.Role.MENU_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_menu_items(root, pred=None): + """Returns all descendants of root with the menu item role""" + + roles = [Atspi.Role.MENU_ITEM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_menu_items_of_any_kind(root, pred=None): + """Returns all descendants of root that has any menu item role""" + + roles = AXUtilitiesRole.get_menu_item_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_menu_related_objects(root, pred=None): + """Returns all descendants of root that has any menu-related role""" + + roles = AXUtilitiesRole.get_menu_related_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_modal_dialogs(root, pred=None): + """Returns all descendants of root with the alert or dialog role and modal state""" + + roles = AXUtilitiesRole.get_dialog_roles(True) + states = [Atspi.StateType.MODAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_multi_line_entries(root, pred=None): + """Returns all descendants of root with the entry role and multiline state""" + + roles = [Atspi.Role.ENTRY] + states = [Atspi.StateType.MULTI_LINE] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_notifications(root, pred=None): + """Returns all descendants of root with the notification role""" + + roles = [Atspi.Role.NOTIFICATION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_option_panes(root, pred=None): + """Returns all descendants of root with the option pane role""" + + roles = [Atspi.Role.OPTION_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_pages(root, pred=None): + """Returns all descendants of root with the page role""" + + roles = [Atspi.Role.PAGE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_page_tabs(root, pred=None): + """Returns all descendants of root with the page tab role""" + + roles = [Atspi.Role.PAGE_TAB] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_page_tab_lists(root, pred=None): + """Returns all descendants of root with the page tab list role""" + + roles = [Atspi.Role.PAGE_TAB_LIST] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_page_tab_list_related_objects(root, pred=None): + """Returns all descendants of root with the page tab or page tab list role""" + + roles = [Atspi.Role.PAGE_TAB_LIST, Atspi.Role.PAGE_TAB] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_panels(root, pred=None): + """Returns all descendants of root with the panel role""" + + roles = [Atspi.Role.PANEL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_paragraphs(root, treat_headings_as_paragraphs=False, pred=None): + """Returns all descendants of root with the paragraph role""" + + roles = [Atspi.Role.PARAGRAPH] + if treat_headings_as_paragraphs: + roles.append(Atspi.Role.HEADING) + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_password_texts(root, pred=None): + """Returns all descendants of root with the password text role""" + + roles = [Atspi.Role.PASSWORD_TEXT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_popup_menus(root, pred=None): + """Returns all descendants of root with the popup menu role""" + + roles = [Atspi.Role.POPUP_MENU] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_progress_bars(root, pred=None): + """Returns all descendants of root with the progress bar role""" + + roles = [Atspi.Role.PROGRESS_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_push_buttons(root, pred=None): + """Returns all descendants of root with the push button role""" + + roles = [Atspi.Role.PUSH_BUTTON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_push_button_menus(root, pred=None): + """Returns all descendants of root with the push button menu role""" + + roles = [Atspi.Role.PUSH_BUTTON_MENU] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_radio_buttons(root, pred=None): + """Returns all descendants of root with the radio button role""" + + roles = [Atspi.Role.RADIO_BUTTON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_radio_menu_items(root, pred=None): + """Returns all descendants of root with the radio menu item role""" + + roles = [Atspi.Role.RADIO_MENU_ITEM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_ratings(root, pred=None): + """Returns all descendants of root with the rating role""" + + roles = [Atspi.Role.RATING] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_root_panes(root, pred=None): + """Returns all descendants of root with the root pane role""" + + roles = [Atspi.Role.ROOT_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_row_headers(root, pred=None): + """Returns all descendants of root with the row header role""" + + roles = [Atspi.Role.ROW_HEADER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_rulers(root, pred=None): + """Returns all descendants of root with the ruler role""" + + roles = [Atspi.Role.RULER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_scroll_bars(root, pred=None): + """Returns all descendants of root with the scrollbar role""" + + roles = [Atspi.Role.SCROLL_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_scroll_panes(root, pred=None): + """Returns all descendants of root with the scroll pane role""" + + roles = [Atspi.Role.SCROLL_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_sections(root, pred=None): + """Returns all descendants of root with the section role""" + + roles = [Atspi.Role.SECTION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_selectable_objects(root, pred=None): + """Returns all descendants of root which are selectable""" + + states = [Atspi.StateType.SELECTABLE] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_selected_objects(root, pred=None): + """Returns all descendants of root which are selected""" + + states = [Atspi.StateType.SELECTED] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_separators(root, pred=None): + """Returns all descendants of root with the separator role""" + + roles = [Atspi.Role.SEPARATOR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_set_containers(root, pred=None): + """Returns all descendants of root with a set container role""" + + roles = AXUtilitiesRole.get_set_container_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_showing_objects(root, pred=None): + """Returns all descendants of root which are showing""" + + states = [Atspi.StateType.SHOWING] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_showing_and_visible_objects(root, pred=None): + """Returns all descendants of root which are showing and visible""" + + states = [Atspi.StateType.SHOWING, Atspi.StateType.VISIBLE] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_showing_or_visible_objects(root, pred=None): + """Returns all descendants of root which are showing or visible""" + + states = [Atspi.StateType.SHOWING, Atspi.StateType.VISIBLE] + return AXUtilitiesCollection.find_all_with_any_state(root, states, pred) + + @staticmethod + def find_all_single_line_entries(root, pred=None): + """Returns all descendants of root with the entry role and multiline state""" + + roles = [Atspi.Role.ENTRY] + states = [Atspi.StateType.SINGLE_LINE] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_sliders(root, pred=None): + """Returns all descendants of root with the slider role""" + + roles = [Atspi.Role.SLIDER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_spin_buttons(root, pred=None): + """Returns all descendants of root with the spin button role""" + + roles = [Atspi.Role.SPIN_BUTTON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_split_panes(root, pred=None): + """Returns all descendants of root with the split pane role""" + + roles = [Atspi.Role.SPLIT_PANE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_statics(root, pred=None): + """Returns all descendants of root with the static role""" + + roles = [Atspi.Role.STATIC] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_status_bars(root, pred=None): + """Returns all descendants of root with the statusbar role""" + + roles = [Atspi.Role.STATUS_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_subscripts(root, pred=None): + """Returns all descendants of root with the subscript role""" + + roles = [Atspi.Role.SUBSCRIPT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_subscripts_and_superscripts(root, pred=None): + """Returns all descendants of root with the subscript or superscript role""" + + roles = [Atspi.Role.SUBSCRIPT, Atspi.Role.SUPERSCRIPT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_suggestions(root, pred=None): + """Returns all descendants of root with the suggestion role""" + + roles = [Atspi.Role.SUGGESTION] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_superscripts(root, pred=None): + """Returns all descendants of root with the superscript role""" + + roles = [Atspi.Role.SUPERSCRIPT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_supports_action(root, pred=None): + """Returns all descendants of root which support the action interface""" + + interfaces = ["Action"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_document(root, pred=None): + """Returns all descendants of root which support the document interface""" + + interfaces = ["Document"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_editable_text(root, pred=None): + """Returns all descendants of root which support the editable text interface""" + + interfaces = ["EditableText"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_hypertext(root, pred=None): + """Returns all descendants of root which support the hypertext interface""" + + interfaces = ["Hypertext"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_hyperlink(root, pred=None): + """Returns all descendants of root which support the hyperlink interface""" + + interfaces = ["Hyperlink"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_selection(root, pred=None): + """Returns all descendants of root which support the selection interface""" + + interfaces = ["Selection"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_table(root, pred=None): + """Returns all descendants of root which support the table interface""" + + interfaces = ["Table"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_table_cell(root, pred=None): + """Returns all descendants of root which support the table cell interface""" + + interfaces = ["TableCell"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_text(root, pred=None): + """Returns all descendants of root which support the text interface""" + + interfaces = ["Text"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_supports_value(root, pred=None): + """Returns all descendants of root which support the value interface""" + + interfaces = ["Value"] + return AXUtilitiesCollection.find_all_with_interfaces(root, interfaces, pred) + + @staticmethod + def find_all_tables(root, pred=None): + """Returns all descendants of root with the table role""" + + roles = [Atspi.Role.TABLE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_cells(root, pred=None): + """Returns all descendants of root with the table cell role""" + + roles = [Atspi.Role.TABLE_CELL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_cells_and_headers(root, pred=None): + """Returns all descendants of root with the table cell or a header-related role""" + + roles = AXUtilitiesRole.get_table_cell_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_column_headers(root, pred=None): + """Returns all descendants of root with the table column header role""" + + roles = [Atspi.Role.TABLE_COLUMN_HEADER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_headers(root, pred=None): + """Returns all descendants of root that has a table header related role""" + + roles = AXUtilitiesRole.get_table_header_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_related_objects(root, pred=None, include_caption=False): + """Returns all descendants of root that has a table related role""" + + roles = AXUtilitiesRole.get_table_related_roles(include_caption) + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_rows(root, pred=None): + """Returns all descendants of root with the table row role""" + + roles = [Atspi.Role.TABLE_ROW] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_table_row_headers(root, pred=None): + """Returns all descendants of root with the table row header role""" + + roles = [Atspi.Role.TABLE_ROW_HEADER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_tearoff_menu_items(root, pred=None): + """Returns all descendants of root with the tearoff menu item role""" + + roles = [Atspi.Role.TEAROFF_MENU_ITEM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_terminals(root, pred=None): + """Returns all descendants of root with the terminal role""" + + roles = [Atspi.Role.TERMINAL] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_texts(root, pred=None): + """Returns all descendants of root with the text role""" + + roles = [Atspi.Role.TEXT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_text_inputs(root, pred=None): + """Returns all descendants of root that has any role associated with textual input""" + + roles = [Atspi.Role.ENTRY, Atspi.Role.PASSWORD_TEXT, Atspi.Role.SPIN_BUTTON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_timers(root, pred=None): + """Returns all descendants of root with the timer role""" + + roles = [Atspi.Role.TIMER] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_title_bars(root, pred=None): + """Returns all descendants of root with the titlebar role""" + + roles = [Atspi.Role.TITLE_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_toggle_buttons(root, pred=None): + """Returns all descendants of root with the toggle button role""" + + roles = [Atspi.Role.TOGGLE_BUTTON] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_tool_bars(root, pred=None): + """Returns all descendants of root with the toolbar role""" + + roles = [Atspi.Role.TOOL_BAR] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_tool_tips(root, pred=None): + """Returns all descendants of root with the tooltip role""" + + roles = [Atspi.Role.TOOL_TIP] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_trees(root, pred=None): + """Returns all descendants of root with the tree role""" + + roles = [Atspi.Role.TREE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_trees_and_tree_tables(root, pred=None): + """Returns all descendants of root with the tree or tree table role""" + + roles = [Atspi.Role.TREE, Atspi.Role.TREE_TABLE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_tree_related_objects(root, pred=None): + """Returns all descendants of root that has a tree related role""" + + roles = AXUtilitiesRole.get_tree_related_roles() + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_tree_items(root, pred=None): + """Returns all descendants of root with the tree item role""" + + roles = [Atspi.Role.TREE_ITEM] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_tree_tables(root, pred=None): + """Returns all descendants of root with the tree table role""" + + roles = [Atspi.Role.TREE_TABLE] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_unrelated_labels(root, must_be_showing=True, pred=None): + """Returns all the descendants of root that have a label role, but no relations""" + + def _pred(obj): + if AXObject.get_relations(obj): + return False + if pred is not None: + return pred(obj) + return True + + roles = [Atspi.Role.LABEL, Atspi.Role.STATIC] + if not must_be_showing: + matches = AXUtilitiesCollection.find_all_with_role(root, roles, _pred) + else: + states = [Atspi.StateType.SHOWING] + matches = AXUtilitiesCollection.find_all_with_role_and_all_states( + root, roles, states, _pred) + + return matches + + @staticmethod + def find_all_unvisited_links(root, must_be_focusable=True, pred=None): + """Returns all descendants of root with the link role and without the visited state""" + + roles = [Atspi.Role.LINK] + states = [Atspi.StateType.VISITED] + result = AXUtilitiesCollection.find_all_with_role_without_states(root, roles, states, pred) + if must_be_focusable: + result = list(filter(AXUtilitiesState.is_focusable, result)) + return result + + @staticmethod + def find_all_vertical_scrollbars(root, pred=None): + """Returns all descendants of root that is a vertical scrollbar""" + + roles = [Atspi.Role.SCROLL_BAR] + states = [Atspi.StateType.VERTICAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_vertical_separators(root, pred=None): + """Returns all descendants of root that is a vertical separator""" + + roles = [Atspi.Role.SEPARATOR] + states = [Atspi.StateType.VERTICAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_vertical_sliders(root, pred=None): + """Returns all descendants of root that is a vertical slider""" + + roles = [Atspi.Role.SLIDER] + states = [Atspi.StateType.VERTICAL] + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_all_visible_objects(root, pred=None): + """Returns all descendants of root which are visible""" + + states = [Atspi.StateType.VISIBLE] + return AXUtilitiesCollection.find_all_with_states(root, states, pred) + + @staticmethod + def find_all_videos(root, pred=None): + """Returns all descendants of root with the video role""" + + roles = [Atspi.Role.VIDEO] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_viewports(root, pred=None): + """Returns all descendants of root with the viewport role""" + + roles = [Atspi.Role.VIEWPORT] + return AXUtilitiesCollection.find_all_with_role(root, roles, pred) + + @staticmethod + def find_all_visited_links(root, must_be_focusable=True, pred=None): + """Returns all descendants of root with the link role and focused and visited states""" + + roles = [Atspi.Role.LINK] + states = [Atspi.StateType.VISITED] + if must_be_focusable: + states.append(Atspi.StateType.FOCUSABLE) + return AXUtilitiesCollection.find_all_with_role_and_all_states(root, roles, states, pred) + + @staticmethod + def find_default_button(root): + """Returns the default button inside root""" + + roles = [Atspi.Role.PUSH_BUTTON] + states = [Atspi.StateType.IS_DEFAULT] + rule = AXCollection.create_match_rule(roles=roles, states=states) + return AXCollection.get_first_match(root, rule) + + @staticmethod + def find_focused_object(root): + """Returns the focused object inside root""" + + states = [Atspi.StateType.FOCUSED] + rule = AXCollection.create_match_rule(states=states) + return AXCollection.get_first_match(root, rule) + + @staticmethod + def find_status_bar(root): + """Returns the status bar inside root""" + + roles = [Atspi.Role.STATUS_BAR] + states = [Atspi.StateType.SHOWING, Atspi.StateType.VISIBLE] + rule = AXCollection.create_match_rule(roles=roles, states=states) + return AXCollection.get_first_match(root, rule) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_role.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_role.py new file mode 100644 index 0000000..fdb7f6a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_role.py @@ -0,0 +1,1467 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for obtaining role-related information. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from .ax_object import AXObject + +class AXUtilitiesRole: + """Utilities for obtaining role-related information.""" + + @staticmethod + def get_dialog_roles(include_alert_as_dialog=True): + """Returns the list of roles we consider documents""" + + roles = [Atspi.Role.COLOR_CHOOSER, + Atspi.Role.DIALOG, + Atspi.Role.FILE_CHOOSER] + if include_alert_as_dialog: + roles.append(Atspi.Role.ALERT) + return roles + + @staticmethod + def get_document_roles(): + """Returns the list of roles we consider documents""" + + roles = [Atspi.Role.DOCUMENT_EMAIL, + Atspi.Role.DOCUMENT_FRAME, + Atspi.Role.DOCUMENT_PRESENTATION, + Atspi.Role.DOCUMENT_SPREADSHEET, + Atspi.Role.DOCUMENT_TEXT, + Atspi.Role.DOCUMENT_WEB] + return roles + + @staticmethod + def get_form_field_roles(): + """Returns the list of roles we consider form fields""" + + roles = [Atspi.Role.CHECK_BOX, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.COMBO_BOX, + Atspi.Role.DOCUMENT_FRAME, # rich text editing pred recommended + Atspi.Role.TEXT, # predicate recommended to check it is editable + Atspi.Role.LIST_BOX, + Atspi.Role.ENTRY, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.SPIN_BUTTON] + return roles + + @staticmethod + def get_menu_item_roles(): + """Returns the list of roles we consider menu items""" + + roles = [Atspi.Role.MENU_ITEM, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.TEAROFF_MENU_ITEM] + return roles + + @staticmethod + def get_menu_related_roles(): + """Returns the list of roles we consider menu related""" + + roles = [Atspi.Role.MENU, + Atspi.Role.MENU_BAR, + Atspi.Role.POPUP_MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.TEAROFF_MENU_ITEM] + return roles + + @staticmethod + def get_roles_to_exclude_from_clickables_list(): + """Returns the list of roles we want to exclude from the list of clickables""" + + roles = [Atspi.Role.COMBO_BOX, + Atspi.Role.ENTRY, + Atspi.Role.LIST_BOX, + Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.PAGE_TAB, + Atspi.Role.PAGE_TAB_LIST, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.PROGRESS_BAR, + Atspi.Role.SLIDER, + Atspi.Role.SPIN_BUTTON, + Atspi.Role.TOOL_BAR, + Atspi.Role.TREE_ITEM, + Atspi.Role.TREE_TABLE, + Atspi.Role.TREE] + return roles + + @staticmethod + def get_set_container_roles(): + """Returns the list of roles we consider a set container""" + + roles = [Atspi.Role.LIST, + Atspi.Role.MENU, + Atspi.Role.PAGE_TAB_LIST, + Atspi.Role.TABLE, + Atspi.Role.TREE, + Atspi.Role.TREE_TABLE] + return roles + + @staticmethod + def get_table_cell_roles(include_headers=True): + """Returns the list of roles we consider table cells""" + + roles = [Atspi.Role.TABLE_CELL] + if include_headers: + roles.extend([Atspi.Role.TABLE_COLUMN_HEADER, + Atspi.Role.TABLE_ROW_HEADER, + Atspi.Role.COLUMN_HEADER, + Atspi.Role.ROW_HEADER]) + return roles + + @staticmethod + def get_table_header_roles(): + """Returns the list of roles we consider table headers""" + + roles = [Atspi.Role.TABLE_COLUMN_HEADER, + Atspi.Role.TABLE_ROW_HEADER, + Atspi.Role.COLUMN_HEADER, + Atspi.Role.ROW_HEADER] + return roles + + @staticmethod + def get_table_related_roles(include_caption=False): + """Returns the list of roles we consider table related""" + + roles = [Atspi.Role.TABLE, + Atspi.Role.TABLE_CELL, + Atspi.Role.TABLE_COLUMN_HEADER, + Atspi.Role.TABLE_ROW_HEADER, + Atspi.Role.COLUMN_HEADER, + Atspi.Role.ROW_HEADER] + if include_caption: + roles.append(Atspi.Role.CAPTION) + return roles + + @staticmethod + def get_tree_related_roles(): + """Returns the list of roles we consider tree related""" + + roles = [Atspi.Role.TREE, + Atspi.Role.TREE_ITEM, + Atspi.Role.TREE_TABLE] + return roles + + @staticmethod + def get_widget_roles(): + """Returns the list of roles we consider widgets""" + + roles = [Atspi.Role.CHECK_BOX, + Atspi.Role.COMBO_BOX, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.SLIDER, + Atspi.Role.TEXT, # predicate recommended to check it is editable + Atspi.Role.TOGGLE_BUTTON] + return roles + + @staticmethod + def have_same_role(obj1, obj2): + """Returns True if obj1 and obj2 have the same role""" + + return AXObject.get_role(obj1) == AXObject.get_role(obj2) + + @staticmethod + def is_accelerator_label(obj, role=None): + """Returns True if obj has the accelerator label role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ACCELERATOR_LABEL + + @staticmethod + def is_alert(obj, role=None): + """Returns True if obj has the alert role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ALERT + + @staticmethod + def is_animation(obj, role=None): + """Returns True if obj has the animation role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ANIMATION + + @staticmethod + def is_application(obj, role=None): + """Returns True if obj has the application role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.APPLICATION + + @staticmethod + def is_arrow(obj, role=None): + """Returns True if obj has the arrow role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ARROW + + @staticmethod + def is_article(obj, role=None): + """Returns True if obj has the article role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ARTICLE + + @staticmethod + def is_audio(obj, role=None): + """Returns True if obj has the audio role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.AUDIO + + @staticmethod + def is_autocomplete(obj, role=None): + """Returns True if obj has the autocomplete role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.AUTOCOMPLETE + + @staticmethod + def is_block_quote(obj, role=None): + """Returns True if obj has the block quote role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.BLOCK_QUOTE + + @staticmethod + def is_button(obj, role=None): + """Returns True if obj has the push- or toggle-button role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.PUSH_BUTTON, Atspi.Role.TOGGLE_BUTTON] + + @staticmethod + def is_calendar(obj, role=None): + """Returns True if obj has the calendar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CALENDAR + + @staticmethod + def is_canvas(obj, role=None): + """Returns True if obj has the canvas role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CANVAS + + @staticmethod + def is_caption(obj, role=None): + """Returns True if obj has the caption role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CAPTION + + @staticmethod + def is_chart(obj, role=None): + """Returns True if obj has the chart role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CHART + + @staticmethod + def is_check_box(obj, role=None): + """Returns True if obj has the checkbox role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CHECK_BOX + + @staticmethod + def is_check_menu_item(obj, role=None): + """Returns True if obj has the check menuitem role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CHECK_MENU_ITEM + + @staticmethod + def is_color_chooser(obj, role=None): + """Returns True if obj has the color_chooser role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.COLOR_CHOOSER + + @staticmethod + def is_column_header(obj, role=None): + """Returns True if obj has the column header role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.COLUMN_HEADER + + @staticmethod + def is_combo_box(obj, role=None): + """Returns True if obj has the combobox role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.COMBO_BOX + + @staticmethod + def is_comment(obj, role=None): + """Returns True if obj has the comment role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.COMMENT + + @staticmethod + def is_content_deletion(obj, role=None): + """Returns True if obj has the content deletion role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CONTENT_DELETION + + @staticmethod + def is_content_insertion(obj, role=None): + """Returns True if obj has the content insertion role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.CONTENT_INSERTION + + @staticmethod + def is_date_editor(obj, role=None): + """Returns True if obj has the date editor role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DATE_EDITOR + + @staticmethod + def is_default_button(obj, role=None): + """Returns True if obj has the push button role the is-default state""" + + return AXUtilitiesRole.is_push_button(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.IS_DEFAULT) + + @staticmethod + def is_definition(obj, role=None): + """Returns True if obj has the definition role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DEFINITION + + @staticmethod + def is_description_list(obj, role=None): + """Returns True if obj has the description list role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DESCRIPTION_LIST + + @staticmethod + def is_description_term(obj, role=None): + """Returns True if obj has the description term role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DESCRIPTION_TERM + + @staticmethod + def is_description_value(obj, role=None): + """Returns True if obj has the description value role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DESCRIPTION_VALUE + + @staticmethod + def is_desktop_frame(obj, role=None): + """Returns True if obj has the desktop frame role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DESKTOP_FRAME + + @staticmethod + def is_desktop_icon(obj, role=None): + """Returns True if obj has the desktop icon role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DESKTOP_ICON + + @staticmethod + def is_dial(obj, role=None): + """Returns True if obj has the dial role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DIAL + + @staticmethod + def is_dialog(obj, role=None): + """Returns True if obj has the dialog role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DIALOG + + @staticmethod + def is_dialog_or_alert(obj, role=None): + """Returns True if obj has any dialog or alert role""" + + roles = AXUtilitiesRole.get_dialog_roles(True) + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_directory_pane(obj, role=None): + """Returns True if obj has the directory pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DIRECTORY_PANE + + @staticmethod + def is_document(obj, role=None): + """Returns True if obj has any document-related role""" + + roles = AXUtilitiesRole.get_document_roles() + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_document_email(obj, role=None): + """Returns True if obj has the document email role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DOCUMENT_EMAIL + + @staticmethod + def is_document_frame(obj, role=None): + """Returns True if obj has the document frame role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DOCUMENT_FRAME + + @staticmethod + def is_document_presentation(obj, role=None): + """Returns True if obj has the document presentation role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DOCUMENT_PRESENTATION + + @staticmethod + def is_document_spreadsheet(obj, role=None): + """Returns True if obj has the document spreadsheet role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DOCUMENT_SPREADSHEET + + @staticmethod + def is_document_text(obj, role=None): + """Returns True if obj has the document text role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DOCUMENT_TEXT + + @staticmethod + def is_document_web(obj, role=None): + """Returns True if obj has the document web role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DOCUMENT_WEB + + @staticmethod + def is_drawing_area(obj, role=None): + """Returns True if obj has the drawing area role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.DRAWING_AREA + + @staticmethod + def is_editbar(obj, role=None): + """Returns True if obj has the editbar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.EDITBAR + + @staticmethod + def is_embedded(obj, role=None): + """Returns True if obj has the embedded role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.EMBEDDED + + @staticmethod + def is_entry(obj, role=None): + """Returns True if obj has the entry role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ENTRY + + @staticmethod + def is_extended(obj, role=None): + """Returns True if obj has the extended role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.EXTENDED + + @staticmethod + def is_file_chooser(obj, role=None): + """Returns True if obj has the file chooser role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FILE_CHOOSER + + @staticmethod + def is_filler(obj, role=None): + """Returns True if obj has the filler role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FILLER + + @staticmethod + def is_focus_traversable(obj, role=None): + """Returns True if obj has the focus traversable role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FOCUS_TRAVERSABLE + + @staticmethod + def is_font_chooser(obj, role=None): + """Returns True if obj has the font chooser role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FONT_CHOOSER + + @staticmethod + def is_footer(obj, role=None): + """Returns True if obj has the footer role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FOOTER + + @staticmethod + def is_footnote(obj, role=None): + """Returns True if obj has the footnote role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FOOTNOTE + + @staticmethod + def is_form(obj, role=None): + """Returns True if obj has the form role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FORM + + @staticmethod + def is_frame(obj, role=None): + """Returns True if obj has the frame role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.FRAME + + @staticmethod + def is_glass_pane(obj, role=None): + """Returns True if obj has the glass pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.GLASS_PANE + + @staticmethod + def is_grouping(obj, role=None): + """Returns True if obj has the grouping role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.GROUPING + + @staticmethod + def is_header(obj, role=None): + """Returns True if obj has the header role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.HEADER + + @staticmethod + def is_heading(obj, role=None): + """Returns True if obj has the heading role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.HEADING + + @staticmethod + def is_html_container(obj, role=None): + """Returns True if obj has the html container role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.HTML_CONTAINER + + @staticmethod + def is_horizontal_scrollbar(obj, role=None): + """Returns True if obj is a horizontal scrollbar""" + + return AXUtilitiesRole.is_scroll_bar(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL) + + @staticmethod + def is_horizontal_separator(obj, role=None): + """Returns True if obj is a horizontal separator""" + + return AXUtilitiesRole.is_separator(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL) + + @staticmethod + def is_horizontal_slider(obj, role=None): + """Returns True if obj is a horizontal slider""" + + return AXUtilitiesRole.is_slider(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL) + + @staticmethod + def is_icon(obj, role=None): + """Returns True if obj has the icon role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ICON + + @staticmethod + def is_icon_or_canvas(obj, role=None): + """Returns True if obj has the icon or canvas role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.ICON, Atspi.Role.CANVAS] + + @staticmethod + def is_image(obj, role=None): + """Returns True if obj has the image role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.IMAGE + + @staticmethod + def is_image_or_canvas(obj, role=None): + """Returns True if obj has the image or canvas role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.IMAGE, Atspi.Role.CANVAS] + + @staticmethod + def is_image_map(obj, role=None): + """Returns True if obj has the image map role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.IMAGE_MAP + + @staticmethod + def is_info_bar(obj, role=None): + """Returns True if obj has the info bar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.INFO_BAR + + @staticmethod + def is_input_method_window(obj, role=None): + """Returns True if obj has the input method window role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.INPUT_METHOD_WINDOW + + @staticmethod + def is_internal_frame(obj, role=None): + """Returns True if obj has the internal frame role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.INTERNAL_FRAME + + @staticmethod + def is_invalid_role(obj, role=None): + """Returns True if obj has the invalid role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.INVALID + + @staticmethod + def is_label(obj, role=None): + """Returns True if obj has the label role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LABEL + + @staticmethod + def is_label_or_caption(obj, role=None): + """Returns True if obj has the label or caption role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.LABEL, Atspi.Role.CAPTION] + + @staticmethod + def is_landmark(obj, role=None): + """Returns True if obj has the landmark role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LANDMARK + + @staticmethod + def is_layered_pane(obj, role=None): + """Returns True if obj has the layered pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LAYERED_PANE + + @staticmethod + def is_level_bar(obj, role=None): + """Returns True if obj has the level bar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LEVEL_BAR + + @staticmethod + def is_link(obj, role=None): + """Returns True if obj has the link role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LINK + + @staticmethod + def is_list(obj, role=None): + """Returns True if obj has the list role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LIST + + @staticmethod + def is_list_box(obj, role=None): + """Returns True if obj has the list box role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LIST_BOX + + @staticmethod + def is_list_item(obj, role=None): + """Returns True if obj has the list item role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LIST_ITEM + + @staticmethod + def is_log(obj, role=None): + """Returns True if obj has the log role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.LOG + + @staticmethod + def is_mark(obj, role=None): + """Returns True if obj has the mark role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MARK + + @staticmethod + def is_marquee(obj, role=None): + """Returns True if obj has the marquee role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MARQUEE + + @staticmethod + def is_math(obj, role=None): + """Returns True if obj has the math role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MATH + + @staticmethod + def is_math_fraction(obj, role=None): + """Returns True if obj has the math fraction role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MATH_FRACTION + + @staticmethod + def is_math_root(obj, role=None): + """Returns True if obj has the math root role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MATH_ROOT + + @staticmethod + def is_menu(obj, role=None): + """Returns True if obj has the menu role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MENU + + @staticmethod + def is_menu_bar(obj, role=None): + """Returns True if obj has the menubar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MENU_BAR + + @staticmethod + def is_menu_item(obj, role=None): + """Returns True if obj has the menu item role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.MENU_ITEM + + @staticmethod + def is_menu_item_of_any_kind(obj, role=None): + """Returns True if obj has any menu item role""" + + roles = AXUtilitiesRole.get_menu_item_roles() + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_menu_related(obj, role=None): + """Returns True if obj has any menu-related role""" + + roles = AXUtilitiesRole.get_menu_related_roles() + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_modal_dialog(obj, role=None): + """Returns True if obj has the alert or dialog role and modal state""" + + return AXUtilitiesRole.is_dialog_or_alert(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.MODAL) + + @staticmethod + def is_multi_line_entry(obj, role=None): + """Returns True if obj has the entry role and multiline state""" + + return AXUtilitiesRole.is_entry(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.MULTI_LINE) + + @staticmethod + def is_notification(obj, role=None): + """Returns True if obj has the notification role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.NOTIFICATION + + @staticmethod + def is_option_pane(obj, role=None): + """Returns True if obj has the option pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.OPTION_PANE + + @staticmethod + def is_page(obj, role=None): + """Returns True if obj has the page role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PAGE + + @staticmethod + def is_page_tab(obj, role=None): + """Returns True if obj has the page tab role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PAGE_TAB + + @staticmethod + def is_page_tab_list(obj, role=None): + """Returns True if obj has the page tab list role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PAGE_TAB_LIST + + @staticmethod + def is_page_tab_list_related(obj, role=None): + """Returns True if obj has the page tab or page tab list role""" + + roles = [Atspi.Role.PAGE_TAB_LIST, Atspi.Role.PAGE_TAB] + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_panel(obj, role=None): + """Returns True if obj has the panel role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PANEL + + @staticmethod + def is_paragraph(obj, role=None): + """Returns True if obj has the paragraph role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PARAGRAPH + + @staticmethod + def is_password_text(obj, role=None): + """Returns True if obj has the password text role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PASSWORD_TEXT + + @staticmethod + def is_popup_menu(obj, role=None): + """Returns True if obj has the popup menu role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.POPUP_MENU + + @staticmethod + def is_progress_bar(obj, role=None): + """Returns True if obj has the progress bar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PROGRESS_BAR + + @staticmethod + def is_push_button(obj, role=None): + """Returns True if obj has the push button role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PUSH_BUTTON + + @staticmethod + def is_push_button_menu(obj, role=None): + """Returns True if obj has the push button menu role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.PUSH_BUTTON_MENU + + @staticmethod + def is_radio_button(obj, role=None): + """Returns True if obj has the radio button role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.RADIO_BUTTON + + @staticmethod + def is_radio_menu_item(obj, role=None): + """Returns True if obj has the radio menu item role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.RADIO_MENU_ITEM + + @staticmethod + def is_rating(obj, role=None): + """Returns True if obj has the rating role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.RATING + + @staticmethod + def is_redundant_object(obj, role=None): + """Returns True if obj has the redundant object role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.REDUNDANT_OBJECT + + @staticmethod + def is_root_pane(obj, role=None): + """Returns True if obj has the root pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ROOT_PANE + + @staticmethod + def is_row_header(obj, role=None): + """Returns True if obj has the row header role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.ROW_HEADER + + @staticmethod + def is_ruler(obj, role=None): + """Returns True if obj has the ruler role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.RULER + + @staticmethod + def is_scroll_bar(obj, role=None): + """Returns True if obj has the scrollbar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SCROLL_BAR + + @staticmethod + def is_scroll_pane(obj, role=None): + """Returns True if obj has the scroll pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SCROLL_PANE + + @staticmethod + def is_section(obj, role=None): + """Returns True if obj has the section role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SECTION + + @staticmethod + def is_separator(obj, role=None): + """Returns True if obj has the separator role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SEPARATOR + + @staticmethod + def is_single_line_entry(obj, role=None): + """Returns True if obj has the entry role and multiline state""" + + return AXUtilitiesRole.is_entry(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.SINGLE_LINE) + + @staticmethod + def is_slider(obj, role=None): + """Returns True if obj has the slider role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SLIDER + + @staticmethod + def is_spin_button(obj, role=None): + """Returns True if obj has the spin button role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SPIN_BUTTON + + @staticmethod + def is_split_pane(obj, role=None): + """Returns True if obj has the split pane role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SPLIT_PANE + + @staticmethod + def is_static(obj, role=None): + """Returns True if obj has the static role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.STATIC + + @staticmethod + def is_status_bar(obj, role=None): + """Returns True if obj has the statusbar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.STATUS_BAR + + @staticmethod + def is_subscript(obj, role=None): + """Returns True if obj has the subscript role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SUBSCRIPT + + @staticmethod + def is_subscript_or_superscript(obj, role=None): + """Returns True if obj has the subscript or superscript role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.SUBSCRIPT, Atspi.Role.SUPERSCRIPT] + + @staticmethod + def is_suggestion(obj, role=None): + """Returns True if obj has the suggestion role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SUGGESTION + + @staticmethod + def is_superscript(obj, role=None): + """Returns True if obj has the superscript role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.SUPERSCRIPT + + @staticmethod + def is_table(obj, role=None): + """Returns True if obj has the table role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TABLE + + @staticmethod + def is_table_cell(obj, role=None): + """Returns True if obj has the table cell role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TABLE_CELL + + @staticmethod + def is_table_cell_or_header(obj, role=None): + """Returns True if obj has the table cell or a header-related role""" + + roles = AXUtilitiesRole.get_table_cell_roles() + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_table_column_header(obj, role=None): + """Returns True if obj has the table column header role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TABLE_COLUMN_HEADER + + @staticmethod + def is_table_header(obj, role=None): + """Returns True if obj has a table header related role""" + + roles = AXUtilitiesRole.get_table_header_roles() + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_table_related(obj, role=None, include_caption=False): + """Returns True if obj has a table-related role""" + + roles = AXUtilitiesRole.get_table_related_roles(include_caption) + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_table_row(obj, role=None): + """Returns True if obj has the table row role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TABLE_ROW + + @staticmethod + def is_table_row_header(obj, role=None): + """Returns True if obj has the table row header role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TABLE_ROW_HEADER + + @staticmethod + def is_tearoff_menu_item(obj, role=None): + """Returns True if obj has the tearoff menu item role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TEAROFF_MENU_ITEM + + @staticmethod + def is_terminal(obj, role=None): + """Returns True if obj has the terminal role""" + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TERMINAL + + @staticmethod + def is_text(obj, role=None): + """Returns True if obj has the text role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TEXT + + @staticmethod + def is_text_input(obj, role=None): + """Returns True if obj has any role associated with textual input""" + + roles = [Atspi.Role.ENTRY, Atspi.Role.PASSWORD_TEXT, Atspi.Role.SPIN_BUTTON] + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_timer(obj, role=None): + """Returns True if obj has the timer role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TIMER + + @staticmethod + def is_title_bar(obj, role=None): + """Returns True if obj has the titlebar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TITLE_BAR + + @staticmethod + def is_toggle_button(obj, role=None): + """Returns True if obj has the toggle button role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TOGGLE_BUTTON + + @staticmethod + def is_tool_bar(obj, role=None): + """Returns True if obj has the toolbar role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TOOL_BAR + + @staticmethod + def is_tool_tip(obj, role=None): + """Returns True if obj has the tooltip role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TOOL_TIP + + @staticmethod + def is_tree(obj, role=None): + """Returns True if obj has the tree role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TREE + + @staticmethod + def is_tree_or_tree_table(obj, role=None): + """Returns True if obj has the tree or tree table role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.TREE, Atspi.Role.TREE_TABLE] + + @staticmethod + def is_tree_related(obj, role=None): + """Returns True if obj has a tree-related role""" + + roles = [Atspi.Role.TREE, + Atspi.Role.TREE_ITEM, + Atspi.Role.TREE_TABLE] + if role is None: + role = AXObject.get_role(obj) + return role in roles + + @staticmethod + def is_tree_item(obj, role=None): + """Returns True if obj has the tree item role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TREE_ITEM + + @staticmethod + def is_tree_table(obj, role=None): + """Returns True if obj has the tree table role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.TREE_TABLE + + @staticmethod + def is_unknown(obj, role=None): + """Returns True if obj has the unknown role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.UNKNOWN + + @staticmethod + def is_unknown_or_redundant(obj, role=None): + """Returns True if obj has the unknown or redundant object role""" + + if role is None: + role = AXObject.get_role(obj) + return role in [Atspi.Role.UNKNOWN, Atspi.Role.REDUNDANT_OBJECT] + + @staticmethod + def is_vertical_scrollbar(obj, role=None): + """Returns True if obj is a vertical scrollbar""" + + return AXUtilitiesRole.is_scroll_bar(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.VERTICAL) + + @staticmethod + def is_vertical_separator(obj, role=None): + """Returns True if obj is a vertical separator""" + + return AXUtilitiesRole.is_separator(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.VERTICAL) + + @staticmethod + def is_vertical_slider(obj, role=None): + """Returns True if obj is a vertical slider""" + + return AXUtilitiesRole.is_slider(obj, role) \ + and AXObject.has_state(obj, Atspi.StateType.VERTICAL) + + @staticmethod + def is_video(obj, role=None): + """Returns True if obj has the video role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.VIDEO + + @staticmethod + def is_viewport(obj, role=None): + """Returns True if obj has the viewport role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.VIEWPORT + + @staticmethod + def is_window(obj, role=None): + """Returns True if obj has the window role""" + + if role is None: + role = AXObject.get_role(obj) + return role == Atspi.Role.WINDOW diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_state.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_state.py new file mode 100644 index 0000000..23d8e28 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/ax_utilities_state.py @@ -0,0 +1,366 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" +Utilities for obtaining state-related information. +These utilities are app-type- and toolkit-agnostic. Utilities that might have +different implementations or results depending on the type of app (e.g. terminal, +chat, web) or toolkit (e.g. Qt, Gtk) should be in script_utilities.py file(s). + +N.B. There are currently utilities that should never have custom implementations +that live in script_utilities.py files. These will be moved over time. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from .ax_object import AXObject + + +class AXUtilitiesState: + """Utilities for obtaining state-related information.""" + + @staticmethod + def has_no_state(obj): + """Returns true if obj has an empty state set""" + + return AXObject.get_state_set(obj).is_empty() + + @staticmethod + def has_popup(obj): + """Returns true if obj has the has-popup state""" + + return AXObject.has_state(obj, Atspi.StateType.HAS_POPUP) + + @staticmethod + def has_tooltip(obj): + """Returns true if obj has the has-tooltip state""" + + return AXObject.has_state(obj, Atspi.StateType.HAS_TOOLTIP) + + @staticmethod + def is_active(obj): + """Returns true if obj has the active state""" + + return AXObject.has_state(obj, Atspi.StateType.ACTIVE) + + @staticmethod + def is_animated(obj): + """Returns true if obj has the animated state""" + + return AXObject.has_state(obj, Atspi.StateType.ANIMATED) + + @staticmethod + def is_armed(obj): + """Returns true if obj has the armed state""" + + return AXObject.has_state(obj, Atspi.StateType.ARMED) + + @staticmethod + def is_busy(obj): + """Returns true if obj has the busy state""" + + return AXObject.has_state(obj, Atspi.StateType.BUSY) + + @staticmethod + def is_checkable(obj): + """Returns true if obj has the checkable state""" + + if AXObject.has_state(obj, Atspi.StateType.CHECKABLE): + return True + + if AXObject.has_state(obj, Atspi.StateType.CHECKED): + tokens = ["AXUtilitiesState:", obj, "is checked but lacks state checkable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + @staticmethod + def is_checked(obj): + """Returns true if obj has the checked state""" + + if not AXObject.has_state(obj, Atspi.StateType.CHECKED): + return False + + if not AXObject.has_state(obj, Atspi.StateType.CHECKABLE): + tokens = ["AXUtilitiesState:", obj, "is checked but lacks state checkable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return True + + @staticmethod + def is_collapsed(obj): + """Returns true if obj has the collapsed state""" + + return AXObject.has_state(obj, Atspi.StateType.COLLAPSED) + + @staticmethod + def is_default(obj): + """Returns true if obj has the is-default state""" + + return AXObject.has_state(obj, Atspi.StateType.IS_DEFAULT) + + @staticmethod + def is_defunct(obj): + """Returns true if obj has the defunct state""" + + return AXObject.has_state(obj, Atspi.StateType.DEFUNCT) + + @staticmethod + def is_editable(obj): + """Returns true if obj has the editable state""" + + return AXObject.has_state(obj, Atspi.StateType.EDITABLE) + + @staticmethod + def is_enabled(obj): + """Returns true if obj has the enabled state""" + + return AXObject.has_state(obj, Atspi.StateType.ENABLED) + + @staticmethod + def is_expandable(obj): + """Returns true if obj has the expandable state""" + + if AXObject.has_state(obj, Atspi.StateType.EXPANDABLE): + return True + + if AXObject.has_state(obj, Atspi.StateType.EXPANDED): + tokens = ["AXUtilitiesState:", obj, "is expanded but lacks state expandable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + @staticmethod + def is_expanded(obj): + """Returns true if obj has the expanded state""" + + if not AXObject.has_state(obj, Atspi.StateType.EXPANDED): + return False + + if not AXObject.has_state(obj, Atspi.StateType.EXPANDABLE): + tokens = ["AXUtilitiesState:", obj, "is expanded but lacks state expandable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return True + + @staticmethod + def is_focusable(obj): + """Returns true if obj has the focusable state""" + + if AXObject.has_state(obj, Atspi.StateType.FOCUSABLE): + return True + + if AXObject.has_state(obj, Atspi.StateType.FOCUSED): + tokens = ["AXUtilitiesState:", obj, "is focused but lacks state focusable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + @staticmethod + def is_focused(obj): + """Returns true if obj has the focused state""" + + if not AXObject.has_state(obj, Atspi.StateType.FOCUSED): + return False + + if not AXObject.has_state(obj, Atspi.StateType.FOCUSABLE): + tokens = ["AXUtilitiesState:", obj, "is focused but lacks state focusable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return True + + @staticmethod + def is_horizontal(obj): + """Returns true if obj has the horizontal state""" + + return AXObject.has_state(obj, Atspi.StateType.HORIZONTAL) + + @staticmethod + def is_iconified(obj): + """Returns true if obj has the iconified state""" + + return AXObject.has_state(obj, Atspi.StateType.ICONIFIED) + + @staticmethod + def is_indeterminate(obj): + """Returns true if obj has the indeterminate state""" + + return AXObject.has_state(obj, Atspi.StateType.INDETERMINATE) + + @staticmethod + def is_invalid_state(obj): + """Returns true if obj has the invalid_state state""" + + return AXObject.has_state(obj, Atspi.StateType.INVALID) + + @staticmethod + def is_invalid_entry(obj): + """Returns true if obj has the invalid_entry state""" + + return AXObject.has_state(obj, Atspi.StateType.INVALID_ENTRY) + + @staticmethod + def is_modal(obj): + """Returns true if obj has the modal state""" + + return AXObject.has_state(obj, Atspi.StateType.MODAL) + + @staticmethod + def is_multi_line(obj): + """Returns true if obj has the multi_line state""" + + return AXObject.has_state(obj, Atspi.StateType.MULTI_LINE) + + @staticmethod + def is_multiselectable(obj): + """Returns true if obj has the multiselectable state""" + + return AXObject.has_state(obj, Atspi.StateType.MULTISELECTABLE) + + @staticmethod + def is_opaque(obj): + """Returns true if obj has the opaque state""" + + return AXObject.has_state(obj, Atspi.StateType.OPAQUE) + + @staticmethod + def is_pressed(obj): + """Returns true if obj has the pressed state""" + + return AXObject.has_state(obj, Atspi.StateType.PRESSED) + + @staticmethod + def is_read_only(obj): + """Returns true if obj has the read-only state""" + + return AXObject.has_state(obj, Atspi.StateType.READ_ONLY) + + @staticmethod + def is_required(obj): + """Returns true if obj has the required state""" + + return AXObject.has_state(obj, Atspi.StateType.REQUIRED) + + @staticmethod + def is_resizable(obj): + """Returns true if obj has the resizable state""" + + return AXObject.has_state(obj, Atspi.StateType.RESIZABLE) + + @staticmethod + def is_selectable(obj): + """Returns true if obj has the selectable state""" + + return AXObject.has_state(obj, Atspi.StateType.SELECTABLE) + + @staticmethod + def is_selectable_text(obj): + """Returns true if obj has the selectable-text state""" + + return AXObject.has_state(obj, Atspi.StateType.SELECTABLE_TEXT) + + @staticmethod + def is_selected(obj): + """Returns true if obj has the selected state""" + + return AXObject.has_state(obj, Atspi.StateType.SELECTED) + + @staticmethod + def is_sensitive(obj): + """Returns true if obj has the sensitive state""" + + return AXObject.has_state(obj, Atspi.StateType.SENSITIVE) + + @staticmethod + def is_showing(obj): + """Returns true if obj has the showing state""" + + return AXObject.has_state(obj, Atspi.StateType.SHOWING) + + @staticmethod + def is_single_line(obj): + """Returns true if obj has the single-line state""" + + return AXObject.has_state(obj, Atspi.StateType.SINGLE_LINE) + + @staticmethod + def is_stale(obj): + """Returns true if obj has the stale state""" + + return AXObject.has_state(obj, Atspi.StateType.STALE) + + @staticmethod + def is_transient(obj): + """Returns true if obj has the transient state""" + + return AXObject.has_state(obj, Atspi.StateType.TRANSIENT) + + @staticmethod + def is_truncated(obj): + """Returns true if obj has the truncated state""" + + return AXObject.has_state(obj, Atspi.StateType.TRUNCATED) + + @staticmethod + def is_vertical(obj): + """Returns true if obj has the vertical state""" + + return AXObject.has_state(obj, Atspi.StateType.VERTICAL) + + @staticmethod + def is_visible(obj): + """Returns true if obj has the visible state""" + + return AXObject.has_state(obj, Atspi.StateType.VISIBLE) + + @staticmethod + def is_visited(obj): + """Returns true if obj has the visited state""" + + return AXObject.has_state(obj, Atspi.StateType.VISITED) + + @staticmethod + def manages_descendants(obj): + """Returns true if obj has the manages-descendants state""" + + return AXObject.has_state(obj, Atspi.StateType.MANAGES_DESCENDANTS) + + @staticmethod + def supports_autocompletion(obj): + """Returns true if obj has the supports-autocompletion state""" + + return AXObject.has_state(obj, Atspi.StateType.SUPPORTS_AUTOCOMPLETION) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/json_backend.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/json_backend.py new file mode 100644 index 0000000..b98a3b3 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/backends/json_backend.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""JSON backend for Cthulhu settings""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010-2011 Consorcio Fernando de los Rios." +__license__ = "LGPL" + +from json import load, dump +import os +from cthulhu import settings, acss + +class Backend: + + def __init__(self, prefsDir): + """ Initialize the JSON Backend. + """ + self.general = {} + self.pronunciations = {} + self.keybindings = {} + self.profiles = {} + self.settingsFile = os.path.join(prefsDir, "user-settings.conf") + self.appPrefsDir = os.path.join(prefsDir, "app-settings") + + self._defaultProfiles = {'default': { 'profile': settings.profile, + 'pronunciations': {}, + 'keybindings': {} + } + } + + def saveDefaultSettings(self, general, pronunciations, keybindings): + """ Save default settings for all the properties from + cthulhu.settings. """ + prefs = {'general': general, + 'profiles': self._defaultProfiles, + 'pronunciations': pronunciations, + 'keybindings': keybindings} + + self.general = general + self.profiles = self._defaultProfiles + self.pronunciations = pronunciations + self.keybindings = keybindings + + settingsFile = open(self.settingsFile, 'w') + dump(prefs, settingsFile, indent=4) + settingsFile.close() + + def getAppSettings(self, appName): + fileName = os.path.join(self.appPrefsDir, f"{appName}.conf") + if os.path.exists(fileName): + settingsFile = open(fileName, 'r') + prefs = load(settingsFile) + settingsFile.close() + else: + prefs = {} + + return prefs + + def saveAppSettings(self, appName, profile, general, pronunciations, keybindings): + prefs = self.getAppSettings(appName) + profiles = prefs.get('profiles', {}) + profiles[profile] = {'general': general, + 'pronunciations': pronunciations, + 'keybindings': keybindings} + prefs['profiles'] = profiles + + fileName = os.path.join(self.appPrefsDir, f"{appName}.conf") + settingsFile = open(fileName, 'w') + dump(prefs, settingsFile, indent=4) + settingsFile.close() + + def saveProfileSettings(self, profile, general, + pronunciations, keybindings): + """ Save minimal subset defined in the profile against current + defaults. """ + if profile is None: + profile = 'default' + + general['pronunciations'] = pronunciations + general['keybindings'] = keybindings + + with open(self.settingsFile, 'r+') as settingsFile: + prefs = load(settingsFile) + prefs['profiles'][profile] = general + settingsFile.seek(0) + settingsFile.truncate() + dump(prefs, settingsFile, indent=4) + + def _getSettings(self): + """ Load from config file all settings """ + settingsFile = open(self.settingsFile) + try: + prefs = load(settingsFile) + except ValueError: + return + self.general = prefs['general'].copy() + self.pronunciations = prefs['pronunciations'] + self.keybindings = prefs['keybindings'] + self.profiles = prefs['profiles'].copy() + + def getGeneral(self, profile=None): + """ Get general settings from default settings and + override with profile values. """ + self._getSettings() + generalSettings = self.general.copy() + defaultProfile = generalSettings.get('startingProfile', + ['Default', 'default']) + if profile is None: + profile = defaultProfile[1] + profileSettings = self.profiles[profile].copy() + for key, value in profileSettings.items(): + if key == 'voices': + for voiceType, voiceDef in value.items(): + value[voiceType] = acss.ACSS(voiceDef) + if key not in ['startingProfile', 'activeProfile']: + generalSettings[key] = value + try: + generalSettings['activeProfile'] = profileSettings['profile'] + except KeyError: + generalSettings['activeProfile'] = defaultProfile + return generalSettings + + def getPronunciations(self, profile='default'): + """ Get pronunciation settings from default settings and + override with profile values. """ + self._getSettings() + pronunciations = self.pronunciations.copy() + profileSettings = self.profiles[profile].copy() + if 'pronunciations' in profileSettings: + pronunciations = profileSettings['pronunciations'] + return pronunciations + + def getKeybindings(self, profile='default'): + """ Get keybindings settings from default settings and + override with profile values. """ + self._getSettings() + keybindings = self.keybindings.copy() + profileSettings = self.profiles[profile].copy() + if 'keybindings' in profileSettings: + keybindings = profileSettings['keybindings'] + return keybindings + + def isFirstStart(self): + """ Check if we're in first start. """ + + return not os.path.exists(self.settingsFile) + + def _setProfileKey(self, key, value): + self.general[key] = value + + with open(self.settingsFile, 'r+') as settingsFile: + prefs = load(settingsFile) + prefs['general'][key] = value + settingsFile.seek(0) + settingsFile.truncate() + dump(prefs, settingsFile, indent=4) + + def setFirstStart(self, value=False): + """Set firstStart. This user-configurable setting is primarily + intended to serve as an indication as to whether or not initial + configuration is needed.""" + self.general['firstStart'] = value + self._setProfileKey('firstStart', value) + + def availableProfiles(self): + """ List available profiles. """ + self._getSettings() + profiles = [] + + for profileName in self.profiles.keys(): + profileDict = self.profiles[profileName].copy() + profiles.append(profileDict.get('profile')) + + return profiles + + def removeProfile(self, profile): + """Remove an existing profile""" + def removeProfileFrom(dict): + del dict[profile] + # if we removed the last profile, restore the default ones + if len(dict) == 0: + for profileName in self._defaultProfiles: + dict[profileName] = self._defaultProfiles[profileName].copy() + + if profile in self.profiles: + removeProfileFrom(self.profiles) + + with open(self.settingsFile, 'r+') as settingsFile: + prefs = load(settingsFile) + if profile in prefs['profiles']: + removeProfileFrom(prefs['profiles']) + settingsFile.seek(0) + settingsFile.truncate() + dump(prefs, settingsFile, indent=4) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/bookmarks.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/bookmarks.py new file mode 100644 index 0000000..a2c069e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/bookmarks.py @@ -0,0 +1,328 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides the default implementation for bookmarks in Cthulhu.""" + +import pickle +import os +import urllib.parse + +from . import cmdnames +from . import keybindings +from . import input_event +from . import messages +from . import settings_manager +from .ax_object import AXObject + +_settingsManager = settings_manager.getManager() + +class Bookmarks: + """Represents a default bookmark handler.""" + def __init__(self, script): + self._script = script + self._bookmarks = {} + self._saveObservers = [] + self._loadObservers = [] + self._loadBookmarks() + self._currentbookmarkindex = None + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + + def get_bindings(self): + """Returns the bookmark keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the bookmark handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the bookmark input event handlers.""" + + handlers = {} + + handlers["goToPrevBookmark"] = \ + input_event.InputEventHandler( + self.goToPrevBookmark, + cmdnames.BOOKMARK_GO_TO_PREVIOUS) + + handlers["goToNextBookmark"] = \ + input_event.InputEventHandler( + self.goToNextBookmark, + cmdnames.BOOKMARK_GO_TO_NEXT) + + handlers["goToBookmark"] = \ + input_event.InputEventHandler( + self.goToBookmark, + cmdnames.BOOKMARK_GO_TO) + + handlers["addBookmark"] = \ + input_event.InputEventHandler( + self.addBookmark, + cmdnames.BOOKMARK_ADD) + + handlers["saveBookmarks"] = \ + input_event.InputEventHandler( + self.saveBookmarks, + cmdnames.BOOKMARK_SAVE) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the date-and-time-presenter key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "b", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("goToNextBookmark"))) + + bindings.add( + keybindings.KeyBinding( + "b", + keybindings.defaultModifierMask, + keybindings.CTHULHU_SHIFT_MODIFIER_MASK, + self._handlers.get("goToPrevBookmark"))) + + bindings.add( + keybindings.KeyBinding( + "b", + keybindings.defaultModifierMask, + keybindings.CTHULHU_ALT_MODIFIER_MASK, + self._handlers.get("saveBookmarks"))) + + for i in range(6): + bindings.add( + keybindings.KeyBinding( + str(i + 1), + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("goToBookmark"))) + + bindings.add( + keybindings.KeyBinding( + str(i + 1), + keybindings.defaultModifierMask, + keybindings.CTHULHU_ALT_MODIFIER_MASK, + self._handlers.get("addBookmark"))) + + return bindings + + def addSaveObserver(self, observer): + self._saveObservers.append(observer) + + def addLoadObserver(self, observer): + self._loadObservers.append(observer) + + def goToBookmark(self, script, inputEvent, index=None): + """ Go to the bookmark indexed by inputEvent.hw_code """ + # establish the _bookmarks index + index = index or inputEvent.hw_code + + try: + context = self._script.getFlatReviewContext() + context_info = self._bookmarks[index] + context.setCurrent(context_info['line'], context_info['zone'], \ + context_info['word'], context_info['char']) + self._bookmarks[index] = context_info + except KeyError: + self._script.presentMessage(messages.BOOKMARK_NOT_FOUND) + return + + self._script.flatReviewPresenter.present_item(script, inputEvent) + + # update the currentbookmark + self._currentbookmarkindex = index + + def addBookmark(self, script, inputEvent): + """ Add an in-page accessible object bookmark for this key. """ + context = self._script.getFlatReviewContext() + self._bookmarks[inputEvent.hw_code] = self._contextToBookmark(context) + self._script.presentMessage(messages.BOOKMARK_ENTERED) + + def saveBookmarks(self, script, inputEvent): + """ Save the bookmarks for this script. """ + try: + self.saveBookmarksToDisk(self._bookmarks) + self._script.presentMessage(messages.BOOKMARKS_SAVED) + except IOError: + self._script.presentMessage(messages.BOOKMARKS_SAVED_FAILURE) + + # Notify the observers + for o in self._saveObservers: + o() + + def goToNextBookmark(self, script, inputEvent): + """ Go to the next bookmark location. If no bookmark has yet to be + selected, the first bookmark will be used. """ + + # get the hardware keys that have registered bookmarks + hwkeys = sorted(self._bookmarks.keys()) + + # no bookmarks have been entered + if len(hwkeys) == 0: + self._script.presentMessage(messages.BOOKMARKS_NOT_FOUND) + return + # only 1 bookmark or we are just starting out + elif len(hwkeys) == 1 or self._currentbookmarkindex is None: + self.goToBookmark(None, index=hwkeys[0]) + return + + # find current bookmark hw_code in our sorted list. + # Go to next one if possible + try: + index = hwkeys.index(self._currentbookmarkindex) + self.goToBookmark(None, index=hwkeys[index+1]) + except (ValueError, KeyError, IndexError): + self.goToBookmark(None, index=hwkeys[0]) + + def goToPrevBookmark(self, script, inputEvent): + # get the hardware keys that have registered bookmarks + hwkeys = sorted(self._bookmarks.keys()) + + # no bookmarks have been entered + if len(hwkeys) == 0: + self._script.presentMessage(messages.BOOKMARKS_NOT_FOUND) + return + # only 1 bookmark or we are just starting out + elif len(hwkeys) == 1 or self._currentbookmarkindex is None: + self.goToBookmark(None, index=hwkeys[0]) + return + + # find current bookmark hw_code in our sorted list. + # Go to previous one if possible + try: + index = hwkeys.index(self._currentbookmarkindex) + self.goToBookmark(None, index=hwkeys[index-1]) + except (ValueError, KeyError, IndexError): + self.goToBookmark(None, index=hwkeys[0]) + + def _loadBookmarks(self): + """ Load this scripts saved bookmarks.""" + self._bookmarks = self.readBookmarksFromDisk() or {} + + # notify the observers + for o in self._loadObservers: + o() + + def readBookmarksFromDisk(self, filename=None): + """ Read saved bookmarks from disk. Currently an unpickled object + that represents a bookmark """ + filename = filename or self._script.name.split(' ')[0] + cthulhuDir = _settingsManager.getPrefsDir() + if not cthulhuDir: + return + + cthulhuBookmarksDir = os.path.join(cthulhuDir, "bookmarks") + try: + inputFile = open( os.path.join( cthulhuBookmarksDir, \ + f'{filename}.pkl'), "r") + bookmarks = pickle.load(inputFile.buffer) + inputFile.close() + return bookmarks + except (IOError, EOFError, OSError): + return None + + def saveBookmarksToDisk(self, bookmarksObj, filename=None): + """ Write bookmarks to disk. bookmarksObj must be a pickleable + object. """ + filename = filename or self._script.name.split(' ')[0] + cthulhuDir = _settingsManager.getPrefsDir() + cthulhuBookmarksDir = os.path.join(cthulhuDir, "bookmarks") + # create directory if it does not exist. correct place?? + try: + os.stat(cthulhuBookmarksDir) + except OSError: + os.mkdir(cthulhuBookmarksDir) + output = open( os.path.join( cthulhuBookmarksDir, \ + f'{filename}.pkl'), "w", os.O_CREAT) + pickle.dump(bookmarksObj, output.buffer) + output.close() + + def _contextToBookmark(self, context): + """Converts a flat_review.Context object into a bookmark.""" + context_info = {} + context_info['zone'] = context.zoneIndex + context_info['char'] = context.charIndex + context_info['word'] = context.wordIndex + context_info['line'] = context.lineIndex + return context_info + + def _bookmarkToContext(self, bookmark): + """Converts a bookmark into a flat_review.Context object.""" + context = self._script.getFlatReviewContext() + context.setCurrent(bookmark['line'], bookmark['zone'], \ + bookmark['word'], bookmark['char']) + return context + + def getURIKey(self): + """Returns the URI key for a given page as a URI stripped of + parameters?query#fragment as seen in urlparse.""" + uri = self._script.utilities.documentFrameURI() + if uri: + parsed_uri = urllib.parse.urlparse(uri) + return ''.join(parsed_uri[0:3]) + else: + return None + + def pathToObj(self, path): + """Return the object with the given path (relative to the + document frame). """ + returnobj = self._script.utilities.documentFrame() + for childnumber in path: + returnobj = AXObject.get_child(returnobj, childnumber) + if not returnobj: + break + + return returnobj + + def _objToPath(self, start_obj=None): + """Given an object, return it's path from the root accessible. If obj + is not provided, the current caret context is used. """ + if not start_obj: + [start_obj, characterOffset] = self._script.utilities.getCaretContext() + + if not start_obj: + return [] + + if self._script.utilities.isDocument(start_obj): + return [] + + path = [] + path.append(AXObject.get_index_in_parent(start_obj)) + p = AXObject.get_parent(start_obj) + while p: + if self._script.utilities.isDocument(p): + path.reverse() + return path + path.append(AXObject.get_index_in_parent(p)) + p = AXObject.get_parent(p) + + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille.py new file mode 100644 index 0000000..8297cd5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille.py @@ -0,0 +1,2032 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""A very experimental approach to the refreshable Braille display. This +module treats each line of the display as a sequential set of regions, where +each region can potentially backed by an Accessible object. Depending upon +the Accessible object, the cursor routing keys can be used to perform +operations on the Accessible object, such as invoking default actions or +moving the text caret. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import locale +import signal +import os +import re + +from gi.repository import GLib + +from . import brltablenames +from . import cmdnames +from . import debug +from . import logger +from . import cthulhu_state +from . import settings +from . import settings_manager + +from .ax_event_synthesizer import AXEventSynthesizer +from .ax_object import AXObject +from .cthulhu_platform import tablesdir + +_logger = logger.getLogger() +log = _logger.newLog("braille") +_monitor = None +_settingsManager = settings_manager.getManager() + +try: + msg = "BRAILLE: About to import brlapi." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + import brlapi + _brlAPI = None + _brlAPIAvailable = True + _brlAPIRunning = False + _brlAPISourceId = 0 +except Exception: + msg = "BRAILLE: Could not import brlapi." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + _brlAPIAvailable = False + _brlAPIRunning = False +else: + tokens = ["BRAILLE: brlapi imported", brlapi] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + +try: + msg = "BRAILLE: About to import louis." + debug.printMessage(debug.LEVEL_INFO, msg, True) + import louis +except Exception: + msg = "BRAILLE: Could not import liblouis" + debug.printMessage(debug.LEVEL_WARNING, msg, True) + louis = None +else: + tokens = ["BRAILLE: liblouis imported", louis] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + tokens = ["BRAILLE: tables location:", tablesdir] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # TODO: Can we get the tablesdir info at runtime? + if not tablesdir: + msg = "BRAILLE: Disabling liblouis due to unknown table location." \ + "This usually means cthulhu was built before liblouis was installed." + debug.printMessage(debug.LEVEL_INFO, msg, True) + louis = None + +try: + from . import brlmon +except Exception: + settings.enableBrailleMonitor = False + + +# brlapi keys which are not allowed to interrupt speech: +# +dontInteruptSpeechKeys = [] +if _brlAPIAvailable: + dontInteruptSpeechKeys = [ \ + brlapi.KEY_CMD_HWINLT, brlapi.KEY_CMD_HWINRT, \ + brlapi.KEY_CMD_FWINLT, brlapi.KEY_CMD_FWINRT, \ + brlapi.KEY_CMD_FWINLTSKIP, brlapi.KEY_CMD_FWINRTSKIP, \ + brlapi.KEY_CMD_LNUP, brlapi.KEY_CMD_LNDN] + +# Common names for most used BrlTTY commands, to be shown in the GUI: +# ATM, the ones used in default.py are: +# +command_name = {} + +if _brlAPIAvailable: + command_name[brlapi.KEY_CMD_HWINLT] = cmdnames.BRAILLE_LINE_LEFT + command_name[brlapi.KEY_CMD_FWINLT] = cmdnames.BRAILLE_LINE_LEFT + command_name[brlapi.KEY_CMD_FWINLTSKIP] = cmdnames.BRAILLE_LINE_LEFT + command_name[brlapi.KEY_CMD_HWINRT] = cmdnames.BRAILLE_LINE_RIGHT + command_name[brlapi.KEY_CMD_FWINRT] = cmdnames.BRAILLE_LINE_RIGHT + command_name[brlapi.KEY_CMD_FWINRTSKIP] = cmdnames.BRAILLE_LINE_RIGHT + command_name[brlapi.KEY_CMD_LNUP] = cmdnames.BRAILLE_LINE_UP + command_name[brlapi.KEY_CMD_LNDN] = cmdnames.BRAILLE_LINE_DOWN + command_name[brlapi.KEY_CMD_FREEZE] = cmdnames.BRAILLE_FREEZE + command_name[brlapi.KEY_CMD_TOP_LEFT] = cmdnames.BRAILLE_TOP_LEFT + command_name[brlapi.KEY_CMD_BOT_LEFT] = cmdnames.BRAILLE_BOTTOM_LEFT + command_name[brlapi.KEY_CMD_HOME] = cmdnames.BRAILLE_HOME + command_name[brlapi.KEY_CMD_SIXDOTS] = cmdnames.BRAILLE_SIX_DOTS + command_name[brlapi.KEY_CMD_ROUTE] = cmdnames.BRAILLE_ROUTE_CURSOR + command_name[brlapi.KEY_CMD_CUTBEGIN] = cmdnames.BRAILLE_CUT_BEGIN + command_name[brlapi.KEY_CMD_CUTLINE] = cmdnames.BRAILLE_CUT_LINE + +# The size of the physical display (width, height). The coordinate system of +# the display is set such that the upper left is (0,0), x values increase from +# left to right, and y values increase from top to bottom. +# +# For the purposes of testing w/o a braille display, we'll set the display +# size to width=32 and height=1. +# +# [[[TODO: WDW - Only a height of 1 is support at this time.]]] +# +DEFAULT_DISPLAY_SIZE = 32 +_displaySize = [DEFAULT_DISPLAY_SIZE, 1] + +# The list of lines on the display. This represents the entire amount of data +# to be drawn on the display. It will be clipped by the viewport if too large. +# +_lines = [] + +# The region with focus. This will be displayed at the home position. +# +_regionWithFocus = None + +# The last text information painted. This has the following fields: +# +# lastTextObj = the last accessible +# lastCaretOffset = the last caret offset of the last text displayed +# lastLineOffset = the last line offset of the last text displayed +# lastCursorCell = the last cell on the braille display for the caret +# +_lastTextInfo = (None, 0, 0, 0) + +# The viewport is a rectangular region of size _displaySize whose upper left +# corner is defined by the point (x, line number). As such, the viewport is +# identified solely by its upper left point. +# +viewport = [0, 0] + +# The callback to call on a BrlTTY input event. This is passed to +# the init method. +# +_callback = None + +# If True, the given portion of the currently displayed line is showing +# on the display. +# +endIsShowing = False +beginningIsShowing = False + +# 1-based offset saying which braille cell has the cursor. A value +# of 0 means no cell has the cursor. +# +cursorCell = 0 + +# The event source of a timeout used for flashing a message. +# +_flashEventSourceId = 0 + +# Line information saved prior to flashing any messages +# +_saved = None + +# Set to True when we lower our output priority +# +idle = False + +# Translators: These are the braille translation table names for different +# languages. You could read about braille tables at: +# http://en.wikipedia.org/wiki/Braille +# +TABLE_NAMES = {"Cz-Cz-g1": brltablenames.CZ_CZ_G1, + "Es-Es-g1": brltablenames.ES_ES_G1, + "Fr-Ca-g2": brltablenames.FR_CA_G2, + "Fr-Fr-g2": brltablenames.FR_FR_G2, + "Lv-Lv-g1": brltablenames.LV_LV_G1, + "Nl-Nl-g1": brltablenames.NL_NL_G1, + "No-No-g0": brltablenames.NO_NO_G0, + "No-No-g1": brltablenames.NO_NO_G1, + "No-No-g2": brltablenames.NO_NO_G2, + "No-No-g3": brltablenames.NO_NO_G3, + "Pl-Pl-g1": brltablenames.PL_PL_G1, + "Pt-Pt-g1": brltablenames.PT_PT_G1, + "Se-Se-g1": brltablenames.SE_SE_G1, + "ar-ar-g1": brltablenames.AR_AR_G1, + "cy-cy-g1": brltablenames.CY_CY_G1, + "cy-cy-g2": brltablenames.CY_CY_G2, + "de-de-g0": brltablenames.DE_DE_G0, + "de-de-g1": brltablenames.DE_DE_G1, + "de-de-g2": brltablenames.DE_DE_G2, + "en-GB-g2": brltablenames.EN_GB_G2, + "en-gb-g1": brltablenames.EN_GB_G1, + "en-us-g1": brltablenames.EN_US_G1, + "en-us-g2": brltablenames.EN_US_G2, + "fr-ca-g1": brltablenames.FR_CA_G1, + "fr-fr-g1": brltablenames.FR_FR_G1, + "gr-gr-g1": brltablenames.GR_GR_G1, + "hi-in-g1": brltablenames.HI_IN_G1, + "hu-hu-comp8": brltablenames.HU_HU_8DOT, + "hu-hu-g1": brltablenames.HU_HU_G1, + "hu-hu-g2": brltablenames.HU_HU_G2, + "it-it-g1": brltablenames.IT_IT_G1, + "nl-be-g1": brltablenames.NL_BE_G1} + +def listTables(): + tables = {} + try: + for fname in os.listdir(tablesdir): + if fname[-4:] in (".utb", ".ctb"): + alias = fname[:-4] + tables[TABLE_NAMES.get(alias, alias)] = \ + os.path.join(tablesdir, fname) + except OSError: + pass + + return tables + +def getDefaultTable(): + userLocale = locale.getlocale(locale.LC_MESSAGES)[0] + tokens = ["BRAILLE: User locale is", userLocale] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if userLocale in (None, "C"): + userLocale = locale.getdefaultlocale()[0] + tokens = ["BRAILLE: Default locale is", userLocale] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if userLocale in (None, "C"): + msg = "BRAILLE: Locale cannot be determined. Falling back on 'en-us'" + debug.printMessage(debug.LEVEL_INFO, msg, True) + language = "en-us" + else: + language = "-".join(userLocale.split("_")).lower() + + try: + tables = [x for x in os.listdir(tablesdir) if x[-4:] in (".utb", ".ctb")] + except OSError: + tokens = ["BRAILLE: Exception calling os.listdir for", tablesdir] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + + # Some of the tables are probably not a good choice for default table.... + exclude = ["interline", "mathtext"] + + # Some of the tables might be a better default than others. For instance, someone who + # can read grade 2 braille presumably can read grade 1; the reverse is not necessarily + # true. Literary braille might be easier for some users to read than computer braille. + # We can adjust this based on user feedback, but in general the goal is a sane default + # for the largest group of users; not the perfect default for all users. + prefer = ["g1", "g2", "comp6", "comp8"] + + def isCandidate(t): + return t.startswith(language) and not any(e in t for e in exclude) + + tables = list(filter(isCandidate, tables)) + tokens = ["BRAILLE:", len(tables), "candidate tables for locale found:", ', '.join(tables)] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not tables: + return "" + + for p in prefer: + for table in tables: + if p in table: + return os.path.join(tablesdir, table) + + # If we couldn't find a preferred match, just go with the first match for the locale. + return os.path.join(tablesdir, tables[0]) + +if louis: + _defaultContractionTable = getDefaultTable() + tokens = ["BRAILLE: Default contraction table is:", _defaultContractionTable] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + +def _printBrailleEvent(level, command): + """Prints out a Braille event. The given level may be overridden + if the eventDebugLevel (see debug.setEventDebugLevel) is greater in + debug.py. + + Arguments: + - command: the BrlAPI command for the key that was pressed. + """ + + debug.printInputEvent( + level, + f"BRAILLE EVENT: {repr(command)}") + +class Region: + """A Braille region to be displayed on the display. The width of + each region is determined by its string. + """ + + def __init__(self, string, cursorOffset=0, expandOnCursor=False): + """Creates a new Region containing the given string. + + Arguments: + - string: the string to be displayed + - cursorOffset: a 0-based index saying where to draw the cursor + for this Region if it gets focus. + """ + + if not string: + string = "" + + # If louis is None, then we don't go into contracted mode. + self.contracted = settings.enableContractedBraille and louis is not None + + self.expandOnCursor = expandOnCursor + + # The uncontracted string for the line. + # + self.rawLine = string.strip("\n") + + if self.contracted: + self.contractionTable = settings.brailleContractionTable or _defaultContractionTable + if string.strip(): + tokens = ["BRAILLE: Contracting '", string, "' with table", self.contractionTable] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self.string, self.inPos, self.outPos, self.cursorOffset = \ + self.contractLine(self.rawLine, + cursorOffset, expandOnCursor) + else: + if string.strip(): + if not settings.enableContractedBraille: + msg = ( + f"BRAILLE: Not contracting '{string}' " + f"because contracted braille is not enabled." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + msg = ( + f"BRAILLE: Not contracting '{string}' " + f"due to problem with liblouis." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.string = self.rawLine + self.cursorOffset = cursorOffset + + def __str__(self): + return "Region: '%s', %d" % (self.string, self.cursorOffset) + + def processRoutingKey(self, offset): + """Processes a cursor routing key press on this Component. The offset + is 0-based, where 0 represents the leftmost character of string + associated with this region. Note that the zeroeth character may have + been scrolled off the display.""" + pass + + def getAttributeMask(self, getLinkMask=True): + """Creates a string which can be used as the attrOr field of brltty's + write structure for the purpose of indicating text attributes, links, + and selection. + + Arguments: + - getLinkMask: Whether or not we should take the time to get + the attributeMask for links. Reasons we might not want to + include knowing that we will fail and/or it taking an + unreasonable amount of time (AKA Gecko). + """ + + # Create an empty mask. + # + return '\x00' * len(self.string) + + def repositionCursor(self): + """Reposition the cursor offset for contracted mode. + """ + if self.contracted: + self.string, self.inPos, self.outPos, self.cursorOffset = \ + self.contractLine(self.rawLine, + self.cursorOffset, + self.expandOnCursor) + + def contractLine(self, line, cursorOffset=0, expandOnCursor=False): + """Contract the given line. Returns the contracted line, and the + cursor position in the contracted line. + + Arguments: + - line: Line to contract. + - cursorOffset: Offset of cursor,defaults to 0. + - expandOnCursor: Expand word under cursor, False by default. + """ + + try: + cursorOnSpace = line[cursorOffset] == ' ' + except IndexError: + cursorOnSpace = False + + if not expandOnCursor or cursorOnSpace: + mode = 0 + else: + mode = louis.compbrlAtCursor + + contracted, inPos, outPos, cursorPos = \ + louis.translate([self.contractionTable], + line, + cursorPos=cursorOffset, + mode=mode) + + # Make sure the cursor is at a realistic spot. + # Note that if cursorOffset is beyond the end of the buffer, + # a spurious value is returned by liblouis in cursorPos. + # + if cursorOffset >= len(line): + cursorPos = len(contracted) + else: + cursorPos = min(cursorPos, len(contracted)) + + return contracted, inPos, outPos, cursorPos + + def displayToBufferOffset(self, display_offset): + try: + offset = self.inPos[display_offset] + except IndexError: + # Off the chart, we just place the cursor at the end of the line. + offset = len(self.rawLine) + except AttributeError: + # Not in contracted mode. + offset = display_offset + + return offset + + def setContractedBraille(self, contracted): + if contracted: + self.contractionTable = settings.brailleContractionTable or _defaultContractionTable + self.contractRegion() + else: + self.expandRegion() + + def contractRegion(self): + if self.contracted: + return + self.string, self.inPos, self.outPos, self.cursorOffset = \ + self.contractLine(self.rawLine, + self.cursorOffset, + self.expandOnCursor) + self.contracted = True + + def expandRegion(self): + if not self.contracted: + return + self.string = self.rawLine + try: + self.cursorOffset = self.inPos[self.cursorOffset] + except IndexError: + self.cursorOffset = len(self.string) + self.contracted = False + +class Component(Region): + """A subclass of Region backed by an accessible. This Region will react + to any cursor routing key events and perform the default action on the + accessible, if a default action exists. + """ + + def __init__(self, accessible, string, cursorOffset=0, + indicator='', expandOnCursor=False): + """Creates a new Component. + + Arguments: + - accessible: the accessible + - string: the string to use to represent the component + - cursorOffset: a 0-based index saying where to draw the cursor + for this Region if it gets focus. + """ + + Region.__init__(self, string, cursorOffset, expandOnCursor) + if indicator: + if self.string: + self.string = indicator + ' ' + self.string + else: + self.string = indicator + + self.accessible = accessible + + def __str__(self): + return "Component: '%s', %d" % (self.string, self.cursorOffset) + + def getCaretOffset(self, offset): + """Returns the caret position of the given offset if the object + has text with a caret. Otherwise, returns -1. + + Arguments: + - offset: 0-based offset of the cell on the physical display + """ + return -1 + + def processRoutingKey(self, offset): + """Processes a cursor routing key press on this Component. The offset + is 0-based, where 0 represents the leftmost character of string + associated with this region. Note that the zeroeth character may have + been scrolled off the display.""" + + if cthulhu_state.activeScript and cthulhu_state.activeScript.utilities.\ + grabFocusBeforeRouting(self.accessible, offset): + try: + self.accessible.queryComponent().grabFocus() + except Exception: + pass + + if AXObject.do_action(self.accessible, 0): + return + + # Do a mouse button 1 click if we have to. For example, page tabs + # don't have any actions but we want to be able to select them with + # the cursor routing key. + try: + result = AXEventSynthesizer.click_object(self.accessible, 1) + except Exception as error: + tokens = ["ERROR: Could not process routing key:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + if not result: + msg = "INFO: Processing routing key failed" + debug.printMessage(debug.LEVEL_INFO, msg, True) + +class Link(Component): + """A subclass of Component backed by an accessible. This Region will be + marked as a link by dots 7 or 8, depending on the user's preferences. + """ + + def __init__(self, accessible, string, cursorOffset=0): + """Initialize a Link region. similar to Component, but here we always + have the region expand on cursor.""" + Component.__init__(self, accessible, string, cursorOffset, '', True) + + def __str__(self): + return "Link: '%s', %d" % (self.string, self.cursorOffset) + + def getAttributeMask(self, getLinkMask=True): + """Creates a string which can be used as the attrOr field of brltty's + write structure for the purpose of indicating text attributes and + selection. + Arguments: + + - getLinkMask: Whether or not we should take the time to get + the attributeMask for links. Reasons we might not want to + include knowing that we will fail and/or it taking an + unreasonable amount of time (AKA Gecko). + """ + + # Create an link indicator mask. + # + return chr(settings.brailleLinkIndicator) * len(self.string) + +class Text(Region): + """A subclass of Region backed by a Text object. This Region will + react to any cursor routing key events by positioning the caret in + the associated text object. The line displayed will be the + contents of the text object preceded by an optional label. + [[[TODO: WDW - need to add in text selection capabilities. Logged + as bugzilla bug 319754.]]]""" + + def __init__(self, accessible, label="", eol="", + startOffset=None, endOffset=None): + """Creates a new Text region. + + Arguments: + - accessible: the accessible that implements AccessibleText + - label: an optional label to display + """ + + self.accessible = accessible + if cthulhu_state.activeScript and self.accessible: + [string, self.caretOffset, self.lineOffset] = \ + cthulhu_state.activeScript.getTextLineAtCaret( + self.accessible, startOffset=startOffset, endOffset=endOffset) + else: + string = "" + self.caretOffset = 0 + self.lineOffset = 0 + + try: + endOffset = endOffset - self.lineOffset + except TypeError: + endOffset = len(string) + + try: + self.startOffset = startOffset - self.lineOffset + except TypeError: + self.startOffset = 0 + + string = string[self.startOffset:endOffset] + + self.caretOffset -= self.startOffset + + cursorOffset = min(self.caretOffset - self.lineOffset, len(string)) + + self._maxCaretOffset = self.lineOffset + len(string) + + self.eol = eol + + if label: + self.label = label + ' ' + else: + self.label = '' + + string = self.label + string + + cursorOffset += len(self.label) + + Region.__init__(self, string, cursorOffset, True) + + if not self.contracted and not settings.disableBrailleEOL: + self.string += self.eol + elif settings.disableBrailleEOL: + # Ensure there is a place to click on at the end of a line + # so the user can route the caret to the end of the line. + # + self.string += ' ' + + def __str__(self): + return "Text: '%s', %d" % (self.string, self.cursorOffset) + + def repositionCursor(self): + """Attempts to reposition the cursor in response to a new + caret position. If it is possible (i.e., the caret is on + the same line as it was), reposition the cursor and return + True. Otherwise, return False. + """ + + if not _regionWithFocus: + return False + + [string, caretOffset, lineOffset] = \ + cthulhu_state.activeScript.getTextLineAtCaret(self.accessible) + + cursorOffset = min(caretOffset - lineOffset, len(string)) + + if lineOffset != self.lineOffset: + return False + + self.caretOffset = caretOffset + self.lineOffset = lineOffset + + cursorOffset += len(self.label) + + if self.contracted: + self.string, self.inPos, self.outPos, cursorOffset = \ + self.contractLine(self.rawLine, cursorOffset, True) + + self.cursorOffset = cursorOffset + + return True + + def getCaretOffset(self, offset): + """Returns the caret position of the given offset if the object + has text with a caret. Otherwise, returns -1. + + Arguments: + - offset: 0-based offset of the cell on the physical display + """ + offset = self.displayToBufferOffset(offset) + + if offset < 0: + return -1 + + return min(self.lineOffset + offset, self._maxCaretOffset) + + def processRoutingKey(self, offset): + """Processes a cursor routing key press on this Component. The offset + is 0-based, where 0 represents the leftmost character of text + associated with this region. Note that the zeroeth character may have + been scrolled off the display. + """ + + caretOffset = self.getCaretOffset(offset) + + if caretOffset < 0: + return + + cthulhu_state.activeScript.utilities.setCaretOffset( + self.accessible, caretOffset) + + def getAttributeMask(self, getLinkMask=True): + """Creates a string which can be used as the attrOr field of brltty's + write structure for the purpose of indicating text attributes, links, + and selection. + + Arguments: + - getLinkMask: Whether or not we should take the time to get + the attributeMask for links. Reasons we might not want to + include knowing that we will fail and/or it taking an + unreasonable amount of time (AKA Gecko). + """ + + try: + self.accessible.queryText() + except NotImplementedError: + return '' + + # Start with an empty mask. + # + stringLength = len(self.rawLine) - len(self.label) + lineEndOffset = self.lineOffset + stringLength + regionMask = [settings.BRAILLE_UNDERLINE_NONE]*stringLength + + attrIndicator = settings.textAttributesBrailleIndicator + selIndicator = settings.brailleSelectorIndicator + linkIndicator = settings.brailleLinkIndicator + script = cthulhu_state.activeScript + if script is None: + msg = "BRAILLE: Cannot get attribute mask without active script." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return "" + + if getLinkMask and linkIndicator != settings.BRAILLE_UNDERLINE_NONE: + try: + hyperText = self.accessible.queryHypertext() + nLinks = hyperText.getNLinks() + except Exception: + nLinks = 0 + + n = 0 + while n < nLinks: + link = hyperText.getLink(n) + if self.lineOffset <= link.startIndex: + for i in range(link.startIndex, link.endIndex): + try: + regionMask[i] |= linkIndicator + except Exception: + pass + n += 1 + + if attrIndicator: + keys, enabledAttributes = script.utilities.stringToKeysAndDict( + settings.enabledBrailledTextAttributes) + + offset = self.lineOffset + while offset < lineEndOffset: + attributes, startOffset, endOffset = \ + script.utilities.textAttributes(self.accessible, + offset, True) + if endOffset <= offset: + break + mask = settings.BRAILLE_UNDERLINE_NONE + offset = endOffset + for attrib in attributes: + if enabledAttributes.get(attrib, '') != '': + if enabledAttributes[attrib] != attributes[attrib]: + mask = attrIndicator + break + if mask != settings.BRAILLE_UNDERLINE_NONE: + maskStart = max(startOffset - self.lineOffset, 0) + maskEnd = min(endOffset - self.lineOffset, stringLength) + for i in range(maskStart, maskEnd): + regionMask[i] |= attrIndicator + + if selIndicator: + selections = script.utilities.allTextSelections(self.accessible) + for startOffset, endOffset in selections: + maskStart = max(startOffset - self.lineOffset, 0) + maskEnd = min(endOffset - self.lineOffset, stringLength) + for i in range(maskStart, maskEnd): + regionMask[i] |= selIndicator + + if self.contracted: + contractedMask = [0] * len(self.rawLine) + outPos = self.outPos[len(self.label):] + if self.label: + # Transform the offsets. + outPos = \ + [offset - len(self.label) - 1 for offset in outPos] + for i, m in enumerate(regionMask): + try: + contractedMask[outPos[i]] |= m + except IndexError: + continue + regionMask = contractedMask[:len(self.string)] + + # Add empty mask characters for the EOL character as well as for + # any label that might be present. + # + regionMask += [0]*len(self.eol) + + if self.label: + regionMask = [0]*len(self.label) + regionMask + + return ''.join(map(chr, regionMask)) + + def contractLine(self, line, cursorOffset=0, expandOnCursor=True): + contracted, inPos, outPos, cursorPos = Region.contractLine( + self, line, cursorOffset, expandOnCursor) + + return contracted + self.eol, inPos, outPos, cursorPos + + def displayToBufferOffset(self, display_offset): + offset = Region.displayToBufferOffset(self, display_offset) + offset += self.startOffset + offset -= len(self.label) + return offset + + def setContractedBraille(self, contracted): + Region.setContractedBraille(self, contracted) + if not contracted: + self.string += self.eol + +class ReviewComponent(Component): + """A subclass of Component that is to be used for flat review mode.""" + + def __init__(self, accessible, string, cursorOffset, zone): + """Creates a new Component. + + Arguments: + - accessible: the accessible + - string: the string to use to represent the component + - cursorOffset: a 0-based index saying where to draw the cursor + for this Region if it gets focus. + - zone: the flat review Zone associated with this component + """ + Component.__init__(self, accessible, string, + cursorOffset, expandOnCursor=True) + self.zone = zone + + def __str__(self): + return "ReviewComponent: %s, %d" % (self.zone, self.cursorOffset) + +class ReviewText(Region): + """A subclass of Region backed by a Text object. This Region will + does not react to the caret changes, but will react if one updates + the cursorPosition. This class is meant to be used by flat review + mode to show the current character position. + """ + + def __init__(self, accessible, string, lineOffset, zone): + """Creates a new Text region. + + Arguments: + - accessible: the accessible that implements AccessibleText + - string: the string to use to represent the component + - lineOffset: the character offset into where the text line starts + - zone: the flat review Zone associated with this component + """ + Region.__init__(self, string, expandOnCursor=True) + self.accessible = accessible + self.lineOffset = lineOffset + self.zone = zone + + def __str__(self): + return "ReviewText: %s, %d" % (self.zone, self.cursorOffset) + + def getCaretOffset(self, offset): + """Returns the caret position of the given offset if the object + has text with a caret. Otherwise, returns -1. + + Arguments: + - offset: 0-based offset of the cell on the physical display + """ + offset = self.displayToBufferOffset(offset) + + if offset < 0: + return -1 + + return self.lineOffset + offset + + def processRoutingKey(self, offset): + """Processes a cursor routing key press on this Component. The offset + is 0-based, where 0 represents the leftmost character of text + associated with this region. Note that the zeroeth character may have + been scrolled off the display.""" + + caretOffset = self.getCaretOffset(offset) + cthulhu_state.activeScript.utilities.setCaretOffset( + self.accessible, caretOffset) + +class Line: + """A horizontal line on the display. Each Line is composed of a sequential + set of Regions. + """ + + def __init__(self, region=None): + self.regions = [] + self.string = "" + if region: + self.addRegion(region) + + def addRegion(self, region): + self.regions.append(region) + + def addRegions(self, regions): + self.regions.extend(regions) + + def getLineInfo(self, getLinkMask=True): + """Computes the complete string for this line as well as a + 0-based index where the focused region starts on this line. + If the region with focus is not on this line, then the index + will be -1. + + Arguments: + - getLinkMask: Whether or not we should take the time to get + the attributeMask for links. Reasons we might not want to + include knowing that we will fail and/or it taking an + unreasonable amount of time (AKA Gecko). + + Returns [string, offsetIndex, attributeMask, ranges] + """ + + string = "" + focusOffset = -1 + attributeMask = "" + ranges = [] + for region in self.regions: + if region == _regionWithFocus: + focusOffset = len(string) + if region.string: + string += region.string + mask = region.getAttributeMask(getLinkMask) + attributeMask += mask + + words = [word.span() for word in re.finditer(r"(^\s+|\S+\s*)", string)] + span = [] + for start, end in words: + if span and end - span[0] > _displaySize[0]: + ranges.append(span) + span = [] + if not span: + # Subdivide long words that exceed the display width. + wordLength = end - start + if wordLength > _displaySize[0]: + displayWidths = wordLength // _displaySize[0] + if displayWidths: + for i in range(displayWidths): + ranges.append([start + i * _displaySize[0], + start + (i+1) * _displaySize[0]]) + if wordLength % _displaySize[0]: + span = [start + displayWidths * _displaySize[0], end] + else: + continue + else: + span = [start, end] + else: + span[1] = end + if end == focusOffset: + ranges.append(span) + span = [] + else: + if span: + ranges.append(span) + + return [string, focusOffset, attributeMask, ranges] + + def getRegionAtOffset(self, offset): + """Finds the Region at the given 0-based offset in this line. + + Returns the [region, offsetinregion] where the region is + the region at the given offset, and offsetinregion is the + 0-based offset from the beginning of the region, representing + where in the region the given offset is.""" + + # Translate the cursor offset for this line into a cursor offset + # for a region, and then pass the event off to the region for + # handling. + # + foundRegion = None + string = "" + pos = 0 + for region in self.regions: + foundRegion = region + string = string + region.string + if len(string) > offset: + break + else: + pos = len(string) + + if offset >= len(string): + return [None, -1] + else: + return [foundRegion, offset - pos] + + def processRoutingKey(self, offset): + """Processes a cursor routing key press on this Component. The offset + is 0-based, where 0 represents the leftmost character of string + associated with this line. Note that the zeroeth character may have + been scrolled off the display.""" + + [region, regionOffset] = self.getRegionAtOffset(offset) + if region: + region.processRoutingKey(regionOffset) + + def setContractedBraille(self, contracted): + for region in self.regions: + region.setContractedBraille(contracted) + +def getRegionAtCell(cell): + """Given a 1-based cell offset, return the braille region + associated with that cell in the form of [region, offsetinregion] + where 'region' is the region associated with the cell and + 'offsetinregion' is the 0-based offset of where the cell is + in the region, where 0 represents the beginning of the region. + """ + + if len(_lines) > 0: + offset = (cell - 1) + viewport[0] + lineNum = viewport[1] + return _lines[lineNum].getRegionAtOffset(offset) + else: + return [None, -1] + +def getCaretContext(event): + """Gets the accesible and caret offset associated with the given + event. The event should have a BrlAPI event that contains an + argument value that corresponds to a cell on the display. + + Arguments: + - event: an instance of input_event.BrailleEvent. event.event is + the dictionary form of the expanded BrlAPI event. + """ + + offset = event.event["argument"] + [region, regionOffset] = getRegionAtCell(offset + 1) + if region and (isinstance(region, Text) or isinstance(region, ReviewText)): + accessible = region.accessible + caretOffset = region.getCaretOffset(regionOffset) + else: + accessible = None + caretOffset = -1 + + return [accessible, caretOffset] + +def clear(): + """Clears the logical structure, but keeps the Braille display as is + (until a refresh operation). + """ + + global _lines + global _regionWithFocus + global viewport + + _lines = [] + _regionWithFocus = None + viewport = [0, 0] + +def setLines(lines): + global _lines + _lines = lines + +def addLine(line): + """Adds a line to the logical display for painting. The line is added to + the end of the current list of known lines. It is necessary for the + viewport to be over the lines and for refresh to be called for the new + line to be painted. + + Arguments: + - line: an instance of Line to add. + """ + + _lines.append(line) + line._index = len(_lines) + +def getShowingLine(): + """Returns the Line that is currently being painted on the display. + """ + if len(_lines) > 0: + return _lines[viewport[1]] + else: + return Line() + +def setFocus(region, panToFocus=True, getLinkMask=True): + """Specififes the region with focus. This region will be positioned + at the home position if panToFocus is True. + + Arguments: + - region: the given region, which much be in a line that has been + added to the logical display + - panToFocus: whether or not to position the region at the home + position + - getLinkMask: Whether or not we should take the time to get the + attributeMask for links. Reasons we might not want to include + knowing that we will fail and/or it taking an unreasonable + amount of time (AKA Gecko). + """ + + global _regionWithFocus + + _regionWithFocus = region + + if not panToFocus or (not _regionWithFocus): + return + + # Adjust the viewport according to the new region with focus. + # The goal is to have the first cell of the region be in the + # home position, but we will give priority to make sure the + # cursor for the region is on the display. For example, when + # faced with a long text area, we'll show the position with + # the caret vs. showing the beginning of the region. + + lineNum = 0 + done = False + for line in _lines: + for reg in line.regions: + if reg == _regionWithFocus: + viewport[1] = lineNum + done = True + break + if done: + break + else: + lineNum += 1 + + line = _lines[viewport[1]] + [string, offset, attributeMask, ranges] = line.getLineInfo(getLinkMask) + + # If the cursor is too far right, we scroll the viewport + # so the cursor will be on the last cell of the display. + # + if _regionWithFocus.cursorOffset >= _displaySize[0]: + offset += _regionWithFocus.cursorOffset - _displaySize[0] + 1 + + viewport[0] = max(0, offset) + +def _idleBraille(): + """Try to hand off control to other screen readers without completely + shutting down the BrlAPI connection""" + + global idle + + if not idle: + try: + msg = "BRAILLE: Attempting to idle braille." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.setParameter(brlapi.PARAM_CLIENT_PRIORITY, 0, False, 0) + idle = True + except Exception: + msg = "BRAILLE: Idling braille failled. This requires BrlAPI >= 0.8." + debug.printMessage(debug.LEVEL_INFO, msg, True) + pass + else: + msg = "BRAILLE: Idling braille succeeded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + return idle + +def _clearBraille(): + """Clear Braille output, hand off control to other screen readers, without + completely shutting down the BrlAPI connection""" + + if not _brlAPIRunning: + # We do want to try to clear the output we left on the device + init(_callback) + + if _brlAPIRunning: + try: + _brlAPI.writeText("", 0) + _idleBraille() + except Exception: + msg = "BRAILLE: BrlTTY seems to have disappeared." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + shutdown() + +def _enableBraille(): + """Re-enable Braille output after making it idle or clearing it""" + global idle + + tokens = ["BRAILLE: Enabling braille. BrlAPI running:", _brlAPIRunning] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not _brlAPIRunning: + msg = "BRAILLE: Need to initialize first." + debug.printMessage(debug.LEVEL_INFO, msg, True) + init(_callback) + + if _brlAPIRunning: + if idle: + msg = "BRAILLE: Is running, but idling." + debug.printMessage(debug.LEVEL_INFO, msg, True) + try: + # Restore default priority + msg = "BRAILLE: Attempting to de-idle braille." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.setParameter(brlapi.PARAM_CLIENT_PRIORITY, 0, False, 50) + idle = False + except Exception: + msg = "BRAILLE: could not restore priority" + debug.printMessage(debug.LEVEL_WARNING, msg, True) + else: + msg = "BRAILLE: De-idle succeeded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + +def disableBraille(): + """Hand off control to other screen readers, shutting down the BrlAPI + connection if needed""" + + global idle + + tokens = ["BRAILLE: Disabling braille. BrlAPI running:", _brlAPIRunning] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if _brlAPIRunning and not idle: + msg = "BRAILLE: BrlApi running and not idle." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not _idleBraille() and not _settingsManager.getSetting('enableBraille'): + # BrlAPI before 0.8 and we really want to shut down + msg = "BRAILLE: could not go idle, completely shut down" + debug.printMessage(debug.LEVEL_INFO, msg, True) + shutdown() + +def checkBrailleSetting(): + """Disable Braille if it got disabled in the preferences""" + + msg = "BRAILLE: Checking braille setting." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not _settingsManager.getSetting('enableBraille'): + disableBraille() + +def refresh(panToCursor=True, targetCursorCell=0, getLinkMask=True, stopFlash=True): + """Repaints the Braille on the physical display. This clips the entire + logical structure by the viewport and also sets the cursor to the + appropriate location. [[[TODO: WDW - I'm not sure how BrlTTY handles + drawing to displays with more than one line, so I'm only going to handle + drawing one line right now.]]] + + Arguments: + - panToCursor: if True, will adjust the viewport so the cursor is showing. + - targetCursorCell: Only effective if panToCursor is True. + 0 means automatically place the cursor somewhere on the display so + as to minimize movement but show as much of the line as possible. + A positive value is a 1-based target cell from the left side of + the display and a negative value is a 1-based target cell from the + right side of the display. + - getLinkMask: Whether or not we should take the time to get the + attributeMask for links. Reasons we might not want to include + knowing that we will fail and/or it taking an unreasonable + amount of time (AKA Gecko). + - stopFlash: if True, kill any flashed message that may be showing. + """ + + # TODO - JD: Split this work out into smaller methods. + + global endIsShowing + global beginningIsShowing + global cursorCell + global _monitor + global _lastTextInfo + + msg = f"BRAILLE: Refresh. Pan: {panToCursor} target: {targetCursorCell}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if stopFlash: + killFlash(restoreSaved=False) + + # TODO - JD: This should be taken care of in cthulhu.py. + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + if _brlAPIRunning: + msg = "BRAILLE: FIXME - Braille disabled, but not properly shut down." + debug.printMessage(debug.LEVEL_INFO, msg, True) + shutdown() + _lastTextInfo = (None, 0, 0, 0) + return + + if len(_lines) == 0: + _clearBraille() + _lastTextInfo = (None, 0, 0, 0) + return + + lastTextObj, lastCaretOffset, lastLineOffset, lastCursorCell = _lastTextInfo + tokens = ["BRAILLE: Last text object:", lastTextObj, + f"(Caret: {lastCaretOffset}, Line: {lastLineOffset}, Cell: {lastCursorCell})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if _regionWithFocus and isinstance(_regionWithFocus, Text): + currentTextObj = _regionWithFocus.accessible + currentCaretOffset = _regionWithFocus.caretOffset + currentLineOffset = _regionWithFocus.lineOffset + else: + currentTextObj = None + currentCaretOffset = 0 + currentLineOffset = 0 + + onSameLine = currentTextObj and currentTextObj == lastTextObj \ + and currentLineOffset == lastLineOffset + + tokens = ["BRAILLE: Current text object:", currentTextObj, + f"(Caret: {currentCaretOffset}, Line: {currentLineOffset}). On same line:", + bool(onSameLine)] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if targetCursorCell < 0: + targetCursorCell = _displaySize[0] + targetCursorCell + 1 + msg = f"BRAILLE: Adjusted targetCursorCell to: {targetCursorCell}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # If there is no target cursor cell and panning to cursor was + # requested, then try to set one. We + # currently only do this for text objects, and we do so by looking + # at the last position of the caret offset and cursor cell. The + # primary goal here is to keep the cursor movement on the display + # somewhat predictable. + + if panToCursor and targetCursorCell == 0 and onSameLine: + if lastCursorCell == 0: + msg = "BRAILLE: Not adjusting targetCursorCell. User panned caret out of view." + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif lastCaretOffset == currentCaretOffset: + targetCursorCell = lastCursorCell + msg = "BRAILLE: Setting targetCursorCell to previous value. Caret hasn't moved." + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif lastCaretOffset < currentCaretOffset: + newLocation = lastCursorCell + (currentCaretOffset - lastCaretOffset) + if newLocation <= _displaySize[0]: + msg = f"BRAILLE: Setting targetCursorCell based on offset: {newLocation}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + targetCursorCell = newLocation + else: + msg = "BRAILLE: Setting targetCursorCell to end of display." + debug.printMessage(debug.LEVEL_INFO, msg, True) + targetCursorCell = _displaySize[0] + elif lastCaretOffset > currentCaretOffset: + newLocation = lastCursorCell - (lastCaretOffset - currentCaretOffset) + if newLocation >= 1: + msg = f"BRAILLE: Setting targetCursorCell based on offset: {newLocation}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + targetCursorCell = newLocation + else: + msg = "BRAILLE: Setting targetCursorCell to start of display." + debug.printMessage(debug.LEVEL_INFO, msg, True) + targetCursorCell = 1 + + # Now, we figure out the 0-based offset for where the cursor actually is in the string. + + line = _lines[viewport[1]] + [string, focusOffset, attributeMask, ranges] = line.getLineInfo(getLinkMask) + msg = f"BRAILLE: Line {viewport[1]}: '{string}' focusOffset: {focusOffset} {ranges}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + cursorOffset = -1 + if focusOffset >= 0: + cursorOffset = focusOffset + _regionWithFocus.cursorOffset + msg = f"BRAILLE: Cursor offset in line string is: {cursorOffset}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # Now, if desired, we'll automatically pan the viewport to show + # the cursor. If there's no targetCursorCell, then we favor the + # left of the display if we need to pan left, or we favor the + # right of the display if we need to pan right. + # + if panToCursor and (cursorOffset >= 0): + if len(string) <= _displaySize[0] and cursorOffset < _displaySize[0]: + msg = f"BRAILLE: Not adjusting offset {viewport[0]}. Cursor offset fits on display." + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif targetCursorCell: + viewport[0] = max(0, cursorOffset - targetCursorCell + 1) + msg = f"BRAILLE: Adjusting offset to {viewport[0]} based on targetCursorCell." + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif cursorOffset < viewport[0]: + viewport[0] = max(0, cursorOffset) + msg = f"BRAILLE: Adjusting offset to {viewport[0]} (cursor on left)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif cursorOffset >= (viewport[0] + _displaySize[0]): + viewport[0] = max(0, cursorOffset - _displaySize[0] + 1) + msg = f"BRAILLE: Adjusting offset to {viewport[0]} (cursor beyond display end)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + rangeForOffset = _getRangeForOffset(cursorOffset) + viewport[0] = max(0, rangeForOffset[0]) + msg = f"BRAILLE: Adjusting offset to {viewport[0]} (unhandled condition)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + if cursorOffset >= (viewport[0] + _displaySize[0]): + viewport[0] = max(0, cursorOffset - _displaySize[0] + 1) + msg = f"BRAILLE: Readjusting offset to {viewport[0]} (cursor beyond display end)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + startPos, endPos = _adjustForWordWrap(targetCursorCell) + viewport[0] = startPos + + # Now normalize the cursor position to BrlTTY, which uses 1 as + # the first cursor position as opposed to 0. + # + cursorCell = cursorOffset - startPos + if (cursorCell < 0) or (cursorCell >= _displaySize[0]): + cursorCell = 0 + else: + cursorCell += 1 # Normalize to 1-based offset + + logLine = f"BRAILLE LINE: '{string}'" + debug.printMessage(debug.LEVEL_INFO, logLine, True) + log.info(logLine) + + logLine = f" VISIBLE: '{string[startPos:endPos]}', cursor={cursorCell}" + debug.printMessage(debug.LEVEL_INFO, logLine, True) + log.info(logLine) + + substring = string[startPos:endPos] + if attributeMask: + submask = attributeMask[startPos:endPos] + else: + submask = "" + + submask += '\x00' * (len(substring) - len(submask)) + + if _settingsManager.getSetting('enableBraille'): + _enableBraille() + + if _settingsManager.getSetting('enableBraille') and _brlAPIRunning: + writeStruct = brlapi.WriteStruct() + writeStruct.regionBegin = 1 + writeStruct.regionSize = len(substring) + while writeStruct.regionSize < _displaySize[0]: + substring += " " + if attributeMask: + submask += '\x00' + writeStruct.regionSize += 1 + writeStruct.text = substring + writeStruct.cursor = cursorCell + + # [[[WDW - if you want to muck around with the dots on the + # display to do things such as add underlines, you can use + # the attrOr field of the write structure to do so. The + # attrOr field is a string whose length must be the same + # length as the display and whose dots will end up showing + # up on the display. Each character represents a bitfield + # where each bit corresponds to a dot (i.e., bit 0 = dot 1, + # bit 1 = dot 2, and so on). Here's an example that underlines + # all the text.]]] + # + #myUnderline = "" + #for i in range(0, _displaySize[0]): + # myUnderline += '\xc0' + #writeStruct.attrOr = myUnderline + + if attributeMask: + writeStruct.attrOr = submask + + try: + _brlAPI.write(writeStruct) + except Exception: + msg = "BRAILLE: BrlTTY seems to have disappeared." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + shutdown() + + if settings.enableBrailleMonitor: + if not _monitor: + try: + _monitor = brlmon.BrlMon(_displaySize[0]) + _monitor.show_all() + except Exception: + debug.printMessage(debug.LEVEL_WARNING, "brlmon failed") + _monitor = None + if attributeMask: + subMask = attributeMask[startPos:endPos] + else: + subMask = None + if _monitor: + _monitor.writeText(cursorCell, substring, subMask) + elif _monitor: + _monitor.destroy() + _monitor = None + + beginningIsShowing = startPos == 0 + endIsShowing = endPos >= len(string) + + # Remember the text information we were presenting (if any) + # + if _regionWithFocus and isinstance(_regionWithFocus, Text): + _lastTextInfo = (_regionWithFocus.accessible, + _regionWithFocus.caretOffset, + _regionWithFocus.lineOffset, + cursorCell) + else: + _lastTextInfo = (None, 0, 0, 0) + +def _flashCallback(): + global _lines + global _regionWithFocus + global viewport + global _flashEventSourceId + + if _flashEventSourceId: + (_lines, _regionWithFocus, viewport, flashTime) = _saved + refresh(panToCursor=False, stopFlash=False) + _flashEventSourceId = 0 + + return False + +def killFlash(restoreSaved=True): + global _flashEventSourceId + global _lines + global _regionWithFocus + global viewport + if _flashEventSourceId: + if _flashEventSourceId > 0: + GLib.source_remove(_flashEventSourceId) + if restoreSaved: + (_lines, _regionWithFocus, viewport, flashTime) = _saved + refresh(panToCursor=False, stopFlash=False) + _flashEventSourceId = 0 + +def resetFlashTimer(): + global _flashEventSourceId + if _flashEventSourceId > 0: + GLib.source_remove(_flashEventSourceId) + flashTime = _saved[3] + _flashEventSourceId = GLib.timeout_add(flashTime, _flashCallback) + +def _initFlash(flashTime): + """Sets up the state needed to flash a message or clears any existing + flash if nothing is to be flashed. + + Arguments: + - flashTime: if non-0, the number of milliseconds to display the + regions before reverting back to what was there before. + A 0 means to not do any flashing. A negative number + means display the message until some other message + comes along or the user presses a cursor routing key. + """ + + global _saved + global _flashEventSourceId + + if _flashEventSourceId: + if _flashEventSourceId > 0: + GLib.source_remove(_flashEventSourceId) + _flashEventSourceId = 0 + else: + _saved = (_lines, _regionWithFocus, viewport, flashTime) + + if flashTime > 0: + _flashEventSourceId = GLib.timeout_add(flashTime, _flashCallback) + elif flashTime < 0: + _flashEventSourceId = -666 + +def displayRegions(regionInfo, flashTime=0): + """Displays a list of regions on a single line, setting focus to the + specified region. The regionInfo parameter is something that is + typically returned by a call to braille_generator.generateBraille. + + Arguments: + - regionInfo: a list where the first element is a list of regions + to display and the second element is the region + with focus (must be in the list from element 0) + - flashTime: if non-0, the number of milliseconds to display the + regions before reverting back to what was there before. + A 0 means to not do any flashing. A negative number + means display the message until some other message + comes along or the user presses a cursor routing key. + """ + + _initFlash(flashTime) + regions = regionInfo[0] + focusedRegion = regionInfo[1] + + clear() + line = Line() + for item in regions: + line.addRegion(item) + addLine(line) + setFocus(focusedRegion) + refresh(stopFlash=False) + +def displayMessage(message, cursor=-1, flashTime=0): + """Displays a single line, setting the cursor to the given position, + ensuring that the cursor is in view. + + Arguments: + - message: the string to display + - cursor: the 0-based cursor position, where -1 (default) means no cursor + - flashTime: if non-0, the number of milliseconds to display the + regions before reverting back to what was there before. + A 0 means to not do any flashing. A negative number + means display the message until some other message + comes along or the user presses a cursor routing key. + """ + + _initFlash(flashTime) + clear() + region = Region(message, cursor) + addLine(Line(region)) + setFocus(region) + refresh(True, stopFlash=False) + +def displayKeyEvent(event): + """Displays a KeyboardEvent. Typically reserved for locking keys like + Caps Lock and Num Lock.""" + + lockingStateString = event.getLockingStateString() + if lockingStateString: + keyname = event.getKeyName() + msg = f"{keyname} {lockingStateString}" + displayMessage(msg, flashTime=settings.brailleFlashTime) + +def _adjustForWordWrap(targetCursorCell): + startPos = viewport[0] + endPos = startPos + _displaySize[0] + msg = f"BRAILLE: Current range: ({startPos}, {endPos}). Target cell: {targetCursorCell}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not _lines or not settings.enableBrailleWordWrap: + return startPos, endPos + + line = _lines[viewport[1]] + lineString, focusOffset, attributeMask, ranges = line.getLineInfo() + ranges = list(filter(lambda x: x[0] <= startPos + targetCursorCell < x[1], ranges)) + if ranges: + msg = f"BRAILLE: Adjusted range: ({ranges[0][0]}, {ranges[-1][1]})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + if ranges[-1][1] - ranges[0][0] > _displaySize[0]: + msg = "BRAILLE: Not adjusting range which is greater than display size" + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + startPos, endPos = ranges[0][0], ranges[-1][1] + + return startPos, endPos + +def _getRangeForOffset(offset): + string, focusOffset, attributeMask, ranges = _lines[viewport[1]].getLineInfo() + for r in ranges: + if r[0] <= offset < r[1]: + return r + for r in ranges: + if offset == r[1]: + return r + + return [0, 0] + +def panLeft(panAmount=0): + """Pans the display to the left, limiting the pan to the beginning + of the line being displayed. + + Arguments: + - panAmount: the amount to pan. A value of 0 means the entire + width of the physical display. + + Returns True if a pan actually happened. + """ + + oldX = viewport[0] + if panAmount == 0: + oldStart, oldEnd = _getRangeForOffset(oldX) + newStart, newEnd = _getRangeForOffset(oldStart - _displaySize[0]) + panAmount = max(0, min(oldStart - newStart, _displaySize[0])) + + viewport[0] = max(0, viewport[0] - panAmount) + msg = f"BRAILLE: Panning left. Amount: {panAmount} (from {oldX} to {viewport[0]})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return oldX != viewport[0] + +def panRight(panAmount=0): + """Pans the display to the right, limiting the pan to the length + of the line being displayed. + + Arguments: + - panAmount: the amount to pan. A value of 0 means the entire + width of the physical display. + + Returns True if a pan actually happened. + """ + + oldX = viewport[0] + if panAmount == 0: + oldStart, oldEnd = _getRangeForOffset(oldX) + newStart, newEnd = _getRangeForOffset(oldEnd) + panAmount = max(0, min(newStart - oldStart, _displaySize[0])) + + if len(_lines) > 0: + lineNum = viewport[1] + newX = viewport[0] + panAmount + string, focusOffset, attributeMask, ranges = _lines[lineNum].getLineInfo() + if newX < len(string): + viewport[0] = newX + + msg = f"BRAILLE: Panning right. Amount: {panAmount} (from {oldX} to {viewport[0]})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return oldX != viewport[0] + +def panToOffset(offset): + """Automatically pan left or right to make sure the current offset is + showing.""" + + msg = f"BRAILLE: Panning to offset {offset}. Current offset: {viewport[0]}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + while offset < viewport[0]: + if not panLeft(): + break + + while offset >= (viewport[0] + _displaySize[0]): + if not panRight(): + break + +def returnToRegionWithFocus(inputEvent=None): + """Pans the display so the region with focus is displayed. + + Arguments: + - inputEvent: the InputEvent instance that caused this to be called. + + Returns True to mean the command should be consumed. + """ + + setFocus(_regionWithFocus) + refresh(True) + + return True + +def setContractedBraille(event): + """Turns contracted braille on or off based upon the event. + + Arguments: + - event: an instance of input_event.BrailleEvent. event.event is + the dictionary form of the expanded BrlAPI event. + """ + + settings.enableContractedBraille = \ + (event.event["flags"] & brlapi.KEY_FLG_TOGGLE_ON) != 0 + for line in _lines: + line.setContractedBraille(settings.enableContractedBraille) + refresh() + +def processRoutingKey(event): + """Processes a cursor routing key event. + + Arguments: + - event: an instance of input_event.BrailleEvent. event.event is + the dictionary form of the expanded BrlAPI event. + """ + + # If a message is being flashed, we'll use a routing key to dismiss it. + # + if _flashEventSourceId: + killFlash() + return + + cell = event.event["argument"] + + if len(_lines) > 0: + cursor = cell + viewport[0] + lineNum = viewport[1] + _lines[lineNum].processRoutingKey(cursor) + + return True + +def _processBrailleEvent(event): + """Handles BrlTTY command events. This passes commands on to Cthulhu for + processing. + + Arguments: + - event: the BrlAPI input event (expanded) + """ + + _printBrailleEvent(debug.LEVEL_FINE, event) + + consumed = False + + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.signal(signal.SIGALRM, settings.timeoutCallback) + signal.alarm(settings.timeoutTime) + + if _callback: + try: + # Like key event handlers, a return value of True means + # the command was consumed. + # + consumed = _callback(event) + except Exception: + debug.printMessage(debug.LEVEL_WARNING, "Issue processing event:") + debug.printException(debug.LEVEL_WARNING) + consumed = False + + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.alarm(0) + + return consumed + +def _brlAPIKeyReader(source, condition): + """Method to read a key from the BrlAPI bindings. This is a + gobject IO watch handler. + """ + try: + key = _brlAPI.readKey(False) + except Exception: + debug.printMessage(debug.LEVEL_WARNING, "BrlTTY seems to have disappeared:") + debug.printException(debug.LEVEL_WARNING) + shutdown() + return + if key: + _processBrailleEvent(_brlAPI.expandKeyCode(key)) + return _brlAPIRunning + +def setupKeyRanges(keys): + """Hacky method to tell BrlTTY what to send and not send us via + the readKey method. This only works with BrlTTY v3.8 and better. + + Arguments: + -keys: a list of BrlAPI commands. + """ + + msg = "BRAILLE: Setting up key ranges." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not _brlAPIRunning: + init(_callback) + + if not _brlAPIRunning: + msg = "BRAILLE: Not setting up key ranges: BrlAPI not running." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "BRAILLE: Ignoring all key ranges." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.ignoreKeys(brlapi.rangeType_all, [0]) + + keySet = [brlapi.KEY_TYPE_CMD | brlapi.KEY_CMD_ROUTE] + + msg = "BRAILLE: Enabling commands:" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + for key in keys: + keySet.append(brlapi.KEY_TYPE_CMD | key) + + msg = "BRAILLE: Sending keys to BrlAPI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.acceptKeys(brlapi.rangeType_command, keySet) + + msg = "BRAILLE: Key ranges set up." + debug.printMessage(debug.LEVEL_INFO, msg, True) + +def init(callback=None): + """Initializes the braille module, connecting to the BrlTTY driver. + + Arguments: + - callback: the method to call with a BrlTTY input event. + Returns False if BrlTTY cannot be accessed or braille has + not been enabled. + """ + + if not settings.enableBraille: + return False + + global _brlAPI + global _brlAPIRunning + global _brlAPISourceId + global _displaySize + global _callback + global _monitor + + tokens = ["BRAILLE: Initializing. Callback:", callback] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if _brlAPIRunning: + msg = "BRAILLE: BrlAPI is already running." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + _callback = callback + + tokens = ["BRAILLE: WINDOWPATH=", os.environ.get('WINDOWPATH')] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + tokens = ["BRAILLE: XDG_VTNR=", os.environ.get('XDG_VTNR')] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + try: + msg = "BRAILLE: Attempting connection with BrlAPI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + _brlAPI = brlapi.Connection() + tokens = ["BRAILLE: Connection established with BrlAPI:", _brlAPI] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + msg = "BRAILLE: Attempting to enter TTY mode." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + _brlAPI.enterTtyModeWithPath() + msg = "BRAILLE: TTY mode entered." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + _brlAPIRunning = True + + (x, y) = _brlAPI.displaySize + msg = f"BRAILLE: Display size: ({x},{y})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if x == 0: + msg = "BRAILLE: Error - 0 cells suggests display is not yet plugged in." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + raise Exception + + _brlAPISourceId = GLib.io_add_watch(_brlAPI.fileDescriptor, + GLib.PRIORITY_DEFAULT, + GLib.IO_IN, + _brlAPIKeyReader) + + except NameError: + msg = "BRAILLE: Initialization failed: BrlApi is not defined." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + except Exception: + msg = "BRAILLE: Initialization failed." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + debug.printException(debug.LEVEL_WARNING) + + _brlAPIRunning = False + + if not _brlAPI: + return False + + try: + msg = "BRAILLE: Attempting to leave TTY mode." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.leaveTtyMode() + msg = "BRAILLE: TTY mode exited." + debug.printMessage(debug.LEVEL_INFO, msg, True) + except Exception: + msg = "BRAILLE: Exception leaving TTY mode." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + try: + msg = "BRAILLE: Attempting to close connection." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.closeConnection() + msg = "BRAILLE: Connection closed." + debug.printMessage(debug.LEVEL_INFO, msg, True) + except Exception: + msg = "BRAILLE: Exception closing connection." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + _brlAPI = None + return False + + _displaySize = [x, 1] + + # The monitor will be created in refresh if needed. + if _monitor: + _monitor.destroy() + _monitor = None + + clear() + refresh(True) + + msg = "BRAILLE: Initialized" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + +def shutdown(): + """Shuts down the braille module. Returns True if the shutdown procedure + was run. + """ + + msg = "BRAILLE: Attempting braille shutdown." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + global _brlAPI + global _brlAPIRunning + global _brlAPISourceId + global _monitor + global _displaySize + + if _brlAPIRunning: + _brlAPIRunning = False + + msg = "BRAILLE: Removing BrlAPI Source ID." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + GLib.source_remove(_brlAPISourceId) + _brlAPISourceId = 0 + + try: + msg = "BRAILLE: Attempting to leave TTY mode." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.leaveTtyMode() + except Exception: + msg = "BRAILLE: Exception leaving TTY mode." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + else: + msg = "BRAILLE: Leaving TTY mode succeeded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + try: + msg = "BRAILLE: Attempting to close connection." + debug.printMessage(debug.LEVEL_INFO, msg, True) + _brlAPI.closeConnection() + except Exception: + msg = "BRAILLE: Exception closing connection." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + else: + msg = "BRAILLE: Closing connection succeeded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + _brlAPI = None + + if _monitor: + _monitor.destroy() + _monitor = None + _displaySize = [DEFAULT_DISPLAY_SIZE, 1] + else: + msg = "BRAILLE: Braille was not running." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + msg = "BRAILLE: Braille shutdown complete." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_generator.py new file mode 100644 index 0000000..3306c89 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_generator.py @@ -0,0 +1,533 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for obtaining braille presentations for objects.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import braille +from . import debug +from . import generator +from . import messages +from . import object_properties +from . import cthulhu_state +from . import settings +from . import settings_manager +from .ax_object import AXObject +from .ax_utilities import AXUtilities +from .braille_rolenames import shortRoleNames + +_settingsManager = settings_manager.getManager() + +class Space: + """A dummy class to indicate we want to insert a space into an + utterance, but only if there is text prior to the space.""" + def __init__(self, delimiter=" "): + self.delimiter = delimiter + +SPACE = [Space()] + +class BrailleGenerator(generator.Generator): + """Takes accessible objects and produces a list of braille Regions + for those objects. See the generateBraille method, which is the + primary entry point. Subclasses can feel free to override/extend + the brailleGenerators instance field as they see fit.""" + + SKIP_CONTEXT_ROLES = (Atspi.Role.MENU, + Atspi.Role.MENU_BAR, + Atspi.Role.PAGE_TAB_LIST, + Atspi.Role.REDUNDANT_OBJECT, + Atspi.Role.UNKNOWN, + Atspi.Role.COMBO_BOX) + + def __init__(self, script): + generator.Generator.__init__(self, script, "braille") + + def _addGlobals(self, globalsDict): + """Other things to make available from the formatting string. + """ + generator.Generator._addGlobals(self, globalsDict) + globalsDict['space'] = self.space + globalsDict['Component'] = braille.Component + globalsDict['Region'] = braille.Region + globalsDict['Text'] = braille.Text + globalsDict['Link'] = braille.Link + globalsDict['asString'] = self.asString + + def _isCandidateFocusedRegion(self, obj, region): + if not isinstance(region, (braille.Component, braille.Text)): + return False + + if not AXUtilities.have_same_role(obj, region.accessible): + return False + + return AXObject.get_name(obj) == AXObject.get_name(region.accessible) + + def generateBraille(self, obj, **args): + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE GENERATOR: generation disabled", True) + return [[], None] + + if obj == cthulhu_state.locusOfFocus \ + and not args.get('formatType', None): + args['formatType'] = 'focused' + result = self.generate(obj, **args) + + # We guess at the focused region. It's going to be a + # Component or Text region whose accessible is the same + # as the object we're generating braille for. There is + # a small hack-like thing here where we include knowledge + # that we represent the text area of editable comboboxes + # instead of the combobox itself. We also do the same + # for table cells because they sometimes have children + # that we present. + # + try: + focusedRegion = result[0] + except Exception: + focusedRegion = None + + for region in result: + if isinstance(region, (braille.Component, braille.Text)) \ + and self._script.utilities.isSameObject(region.accessible, obj, True): + focusedRegion = region + break + elif isinstance(region, braille.Text) \ + and AXUtilities.is_combo_box(obj) \ + and AXObject.get_parent(region.accessible) == obj: + focusedRegion = region + break + elif isinstance(region, braille.Component) \ + and AXUtilities.is_table_cell(obj) \ + and AXObject.get_parent(region.accessible) == obj: + focusedRegion = region + break + else: + + def pred(x): + return self._isCandidateFocusedRegion(obj, x) + + candidates = list(filter(pred, result)) + tokens = ["BRAILLE GENERATOR: Could not determine focused region for", + obj, "Candidates:", candidates] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if len(candidates) == 1: + focusedRegion = candidates[0] + + return [result, focusedRegion] + + ##################################################################### + # # + # Name, role, and label information # + # # + ##################################################################### + + def _generateRoleName(self, obj, **args): + """Returns the role name for the object in an array of strings, with + the exception that the Atspi.Role.UNKNOWN role will yield an + empty array. Note that a 'role' attribute in args will + override the accessible role of the obj. + """ + + if args.get('isProgressBarUpdate') \ + and not _settingsManager.getSetting('brailleProgressBarUpdates'): + return [] + + result = [] + role = args.get('role', AXObject.get_role(obj)) + verbosityLevel = _settingsManager.getSetting('brailleVerbosityLevel') + + doNotPresent = [Atspi.Role.UNKNOWN, + Atspi.Role.REDUNDANT_OBJECT, + Atspi.Role.FILLER, + Atspi.Role.EXTENDED, + Atspi.Role.LINK] + + # egg-list-box, e.g. privacy panel in gnome-control-center + if AXUtilities.is_list_box(AXObject.get_parent(obj)): + doNotPresent.append(AXObject.get_role(obj)) + + if verbosityLevel == settings.VERBOSITY_LEVEL_BRIEF: + doNotPresent.extend([Atspi.Role.ICON, Atspi.Role.CANVAS]) + + if role == Atspi.Role.HEADING: + level = self._script.utilities.headingLevel(obj) + result.append(object_properties.ROLE_HEADING_LEVEL_BRAILLE % level) + + elif verbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \ + and not args.get('readingRow', False) and role not in doNotPresent: + result.append(self.getLocalizedRoleName(obj, **args)) + return result + + def getLocalizedRoleName(self, obj, **args): + """Returns the localized name of the given Accessible object; the name + is suitable to be brailled. + + Arguments: + - obj: an Accessible object + """ + + if _settingsManager.getSetting('brailleRolenameStyle') \ + == settings.BRAILLE_ROLENAME_STYLE_SHORT: + role = args.get('role', AXObject.get_role(obj)) + rv = shortRoleNames.get(role) + if rv: + return rv + + return super().getLocalizedRoleName(obj, **args) + + def _generateUnrelatedLabels(self, obj, **args): + result = [] + labels = self._script.utilities.unrelatedLabels(obj) + for label in labels: + name = self._generateName(label, **args) + result.extend(name) + + return result + + ##################################################################### + # # + # Keyboard shortcut information # + # # + ##################################################################### + + def _generateAccelerator(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the accelerator for the object, + or an empty array if no accelerator can be found. + """ + + verbosityLevel = _settingsManager.getSetting('brailleVerbosityLevel') + if verbosityLevel == settings.VERBOSITY_LEVEL_BRIEF: + return [] + + result = [] + [mnemonic, shortcut, accelerator] = \ + self._script.utilities.mnemonicShortcutAccelerator(obj) + if accelerator: + result.append("(" + accelerator + ")") + return result + + ##################################################################### + # # + # Hierarchy and related dialog information # + # # + ##################################################################### + + def _generateAlertAndDialogCount(self, obj, **args): + """Returns an array of strings that says how many alerts and dialogs + are associated with the application for this object. [[[WDW - + I wonder if this string should be moved to settings.py.]]] + """ + result = [] + try: + alertAndDialogCount = \ + self._script.utilities.unfocusedAlertAndDialogCount(obj) + except Exception: + alertAndDialogCount = 0 + if alertAndDialogCount > 0: + result.append(messages.dialogCountBraille(alertAndDialogCount)) + + return result + + def _generateAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object. This is typically used to present the context for + an object (e.g., the names of the window, the panels, etc., + that the object is contained in). If the 'priorObj' attribute + of the args dictionary is set, only the differences in + ancestry between the 'priorObj' and the current obj will be + computed. The 'priorObj' is typically set by Cthulhu to be the + previous object with focus. + """ + result = [] + if not _settingsManager.getSetting('enableBrailleContext'): + return result + args['includeContext'] = False + + # Radio button group names are treated separately from the + # ancestors. However, they can appear in the ancestry as a + # labeled panel. So, we need to exclude the first one of + # these things we come across. See also the + # generator.py:_generateRadioButtonGroup method that is + # used to find the radio button group name. + # + role = args.get('role', AXObject.get_role(obj)) + excludeRadioButtonGroup = role == Atspi.Role.RADIO_BUTTON + + parent = AXObject.get_parent_checked(obj) + if parent and (AXObject.get_role(parent) in self.SKIP_CONTEXT_ROLES): + parent = AXObject.get_parent_checked(parent) + while parent: + parentResult = [] + # [[[TODO: WDW - we might want to include more things here + # besides just those things that have labels. For example, + # page tab lists might be a nice thing to include. Logged + # as bugzilla bug 319751.]]] + # + role = AXObject.get_role(parent) + if role != Atspi.Role.FILLER \ + and role != Atspi.Role.INVALID \ + and role != Atspi.Role.SECTION \ + and role != Atspi.Role.SPLIT_PANE \ + and role != Atspi.Role.DESKTOP_FRAME \ + and not self._script.utilities.isLayoutOnly(parent): + args['role'] = role + parentResult = self.generate(parent, **args) + # [[[TODO: HACK - we've discovered oddness in hierarchies + # such as the gedit Edit->Preferences dialog. In this + # dialog, we have labeled groupings of objects. The + # grouping is done via a FILLER with two children - one + # child is the overall label, and the other is the + # container for the grouped objects. When we detect this, + # we add the label to the overall context.]]] + # + if role in [Atspi.Role.FILLER, Atspi.Role.PANEL]: + label = self._script.utilities.displayedLabel(parent) + if label and len(label) and not label.isspace(): + if not excludeRadioButtonGroup: + args['role'] = AXObject.get_role(parent) + parentResult = self.generate(parent, **args) + else: + excludeRadioButtonGroup = False + if result and parentResult: + result.append(braille.Region(" ")) + result.extend(parentResult) + if role == Atspi.Role.EMBEDDED: + break + + parent = AXObject.get_parent_checked(parent) + result.reverse() + return result + + def _generateFocusedItem(self, obj, **args): + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role not in [Atspi.Role.LIST, Atspi.Role.LIST_BOX]: + return result + + if AXObject.supports_selection(obj): + items = self._script.utilities.selectedChildren(obj) + else: + items = [AXUtilities.get_focused_object(obj)] + if not (items and items[0]): + return result + + for item in map(self._generateName, items): + result.extend(item) + + return result + + def _generateTermValueCount(self, obj, **args): + count = self._script.utilities.getValueCountForTerm(obj) + if count < 0: + return [] + + return [f"({messages.valueCountForTerm(count)})"] + + def _generateStatusBar(self, obj, **args): + if not AXUtilities.is_status_bar(obj): + return [] + + items = self._script.utilities.statusBarItems(obj) + if not items or items == [obj]: + return [] + + result = [] + for child in items: + childResult = self.generate(child, includeContext=False) + if childResult: + result.extend(childResult) + result.append(braille.Region(" ")) + + return result + + def _generateListBoxItemWidgets(self, obj, **args): + if not AXUtilities.is_list_box(AXObject.get_parent(obj)): + return [] + + result = [] + for widget in AXUtilities.get_all_widgets(obj): + result.extend(self.generate(widget, includeContext=False)) + result.append(braille.Region(" ")) + return result + + def _generateProgressBarIndex(self, obj, **args): + if not args.get('isProgressBarUpdate') \ + or not self._shouldPresentProgressBarUpdate(obj, **args): + return [] + + acc, updateTime, updateValue = self._getMostRecentProgressBarUpdate() + if acc != obj: + number, count = self.getProgressBarNumberAndCount(obj) + return [f'{number}'] + + return [] + + def _generateProgressBarValue(self, obj, **args): + if args.get('isProgressBarUpdate') \ + and not self._shouldPresentProgressBarUpdate(obj, **args): + return [] + + result = self._generatePercentage(obj, **args) + if obj == cthulhu_state.locusOfFocus and not result: + return [''] + + return result + + def _generatePercentage(self, obj, **args): + percent = self._script.utilities.getValueAsPercent(obj) + if percent is not None: + return [f'{percent}%'] + + return [] + + def _getProgressBarUpdateInterval(self): + interval = _settingsManager.getSetting('progressBarBrailleInterval') + if interval is None: + return super()._getProgressBarUpdateInterval() + + return int(interval) + + def _shouldPresentProgressBarUpdate(self, obj, **args): + if not _settingsManager.getSetting('brailleProgressBarUpdates'): + return False + + return super()._shouldPresentProgressBarUpdate(obj, **args) + + ##################################################################### + # # + # Unfortunate hacks. # + # # + ##################################################################### + + def _generateAsPageTabOrScrollPane(self, obj, **args): + """If this scroll pane is labelled by a page tab, then return the page + tab information for the braille context instead. Thunderbird + folder properties is such a case. See bug #507922 for more + details. + """ + result = [] + labels = self._script.utilities.labelsForObject(obj) + for label in labels: + result.extend(self.generate(label, **args)) + break + + if not result: + # NOTE: there is no REAL_ROLE_SCROLL_PANE in formatting.py + # because currently fallback to the default formatting. + # We will provide the support for someone to override this, + # however, so we use REAL_ROLE_SCROLL_PANE here. + # + oldRole = self._overrideRole('REAL_ROLE_SCROLL_PANE', args) + result.extend(self.generate(obj, **args)) + self._restoreRole(oldRole, args) + return result + + def _generateIncludeContext(self, obj, **args): + """Returns True or False to indicate whether context should be + included or not. + """ + + if args.get('isProgressBarUpdate'): + return False + + # For multiline text areas, we only show the context if we + # are on the very first line. Otherwise, we show only the + # line. + # + include = _settingsManager.getSetting('enableBrailleContext') + if not include: + return include + try: + text = obj.queryText() + except NotImplementedError: + text = None + if text and (self._script.utilities.isTextArea(obj) or AXUtilities.is_label(obj)): + try: + [lineString, startOffset, endOffset] = text.getTextAtOffset( + text.caretOffset, Atspi.TextBoundaryType.LINE_START) + except Exception: + return include + + include = startOffset == 0 + if include: + relation = AXObject.get_relation(obj, Atspi.RelationType.FLOWS_FROM) + if relation: + include = not self._script.utilities.isTextArea(relation.get_target(0)) + return include + + ##################################################################### + # # + # Other things for spacing # + # # + ##################################################################### + + def _generateEol(self, obj, **args): + result = [] + if not _settingsManager.getSetting('disableBrailleEOL'): + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'eol' + result.append(self._script.formatting.getString(**args)) + return result + + def space(self, delimiter=" "): + if delimiter == " ": + return SPACE + else: + return [Space(delimiter)] + + def asString(self, content, delimiter=" "): + combined = "" + prior = None + if isinstance(content, str): + combined = content + elif content and isinstance(content, list): + # Strip off leading and trailing spaces. + # + while content and isinstance(content[0], Space): + content = content[1:] + while content and isinstance(content[-1], Space): + content = content[0:-1] + for element in content: + if isinstance(element, Space) and prior: + combined += element.delimiter + prior = None + else: + prior = self.asString(element) + combined = self._script.utilities.appendString( + combined, prior, delimiter) + return combined diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_rolenames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_rolenames.py new file mode 100644 index 0000000..ab1836a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/braille_rolenames.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Dictionary of abbreviated rolenames for use with braille.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2012 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from .cthulhu_i18n import _ +from .cthulhu_i18n import C_ + +shortRoleNames = { + # Translators: short braille for the rolename of an invalid GUI object. + # We strive to keep it under three characters to preserve real estate. + Atspi.Role.INVALID: _("???"), + + # Translators: short braille for the rolename of an alert dialog. + # NOTE for all the short braille words: they we strive to keep them + # around three characters to preserve real estate on the braille + # display. The letters are chosen to make them unique across all + # other rolenames, and they typically act like an abbreviation. + Atspi.Role.ALERT: _("alrt"), + + # Translators: short braille for the rolename of an animation widget. + Atspi.Role.ANIMATION: _("anim"), + + # Translators: short braille for the rolename of an arrow widget. + Atspi.Role.ARROW: _("arw"), + + # Translators: short braille for the rolename of a calendar widget. + Atspi.Role.CALENDAR: _("cal"), + + # Translators: short braille for the rolename of a canvas widget. + Atspi.Role.CANVAS: _("cnv"), + + # Translators: short braille for the rolename of a caption (e.g., + # table caption). + Atspi.Role.CAPTION: _("cptn"), + + # Translators: short braille for the rolename of a checkbox. + Atspi.Role.CHECK_BOX: _("chk"), + + # Translators: short braille for the rolename of a check menu item. + Atspi.Role.CHECK_MENU_ITEM: _("chk"), + + # Translators: short braille for the rolename of a color chooser. + Atspi.Role.COLOR_CHOOSER: _("clrchsr"), + + # Translators: short braille for the rolename of a column header. + Atspi.Role.COLUMN_HEADER: _("colhdr"), + + # Translators: short braille for the rolename of a combo box. + Atspi.Role.COMBO_BOX: _("cbo"), + + # Translators: short braille for the rolename of a date editor. + Atspi.Role.DATE_EDITOR: _("dat"), + + # Translators: short braille for the rolename of a desktop icon. + Atspi.Role.DESKTOP_ICON: _("icn"), + + # Translators: short braille for the rolename of a desktop frame. + Atspi.Role.DESKTOP_FRAME: _("frm"), + + # Translators: short braille for the rolename of a dial. + # You should attempt to treat it as an abbreviation of + # the translated word for "dial". It is OK to use an + # unabbreviated word as long as it is relatively short. + Atspi.Role.DIAL: C_("shortbraille", "dial"), + + # Translators: short braille for the rolename of a dialog. + Atspi.Role.DIALOG: _("dlg"), + + # Translators: short braille for the rolename of a directory pane. + Atspi.Role.DIRECTORY_PANE: _("dip"), + + # Translators: short braille for the rolename of an HTML document frame. + Atspi.Role.DOCUMENT_FRAME: _("html"), + + # Translators: short braille for the rolename of a drawing area. + Atspi.Role.DRAWING_AREA: _("draw"), + + # Translators: short braille for the rolename of a file chooser. + Atspi.Role.FILE_CHOOSER: _("fchsr"), + + # Translators: short braille for the rolename of a filler. + Atspi.Role.FILLER: _("flr"), + + # Translators: short braille for the rolename of a font chooser. + Atspi.Role.FONT_CHOOSER: _("fnt"), + + # Translators: short braille for the rolename of a form. + # You should attempt to treat it as an abbreviation of + # the translated word for "form". It is OK to use an + # unabbreviated word as long as it is relatively short. + Atspi.Role.FORM: C_("shortbraille", "form"), + + # Translators: short braille for the rolename of a frame. + Atspi.Role.FRAME: _("frm"), + + # Translators: short braille for the rolename of a glass pane. + Atspi.Role.GLASS_PANE: _("gpn"), + + # Translators: short braille for the rolename of a heading. + Atspi.Role.HEADING: _("hdng"), + + # Translators: short braille for the rolename of an html container. + Atspi.Role.HTML_CONTAINER: _("html"), + + # Translators: short braille for the rolename of a icon. + Atspi.Role.ICON: _("icn"), + + # Translators: short braille for the rolename of a image. + Atspi.Role.IMAGE: _("img"), + + # Translators: short braille for the rolename of an internal frame. + Atspi.Role.INTERNAL_FRAME: _("ifrm"), + + # Translators: short braille for the rolename of a label. + Atspi.Role.LABEL: _("lbl"), + + # Translators: short braille for the rolename of a layered pane. + Atspi.Role.LAYERED_PANE: _("lyrdpn"), + + # Translators: short braille for the rolename of a link. + Atspi.Role.LINK: _("lnk"), + + # Translators: short braille for the rolename of a list. + Atspi.Role.LIST: _("lst"), + + # Translators: short braille for the rolename of a list item. + Atspi.Role.LIST_ITEM: _("lstitm"), + + # Translators: short braille for the rolename of a menu. + Atspi.Role.MENU: _("mnu"), + + # Translators: short braille for the rolename of a menu bar. + Atspi.Role.MENU_BAR: _("mnubr"), + + # Translators: short braille for the rolename of a menu item. + Atspi.Role.MENU_ITEM: _("mnuitm"), + + # Translators: short braille for the rolename of an option pane. + Atspi.Role.OPTION_PANE: _("optnpn"), + + # Translators: short braille for the rolename of a page tab. + Atspi.Role.PAGE_TAB: _("pgt"), + + # Translators: short braille for the rolename of a page tab list. + Atspi.Role.PAGE_TAB_LIST: _("tblst"), + + # Translators: short braille for the rolename of a panel. + Atspi.Role.PANEL: _("pnl"), + + # Translators: short braille for the rolename of a password field. + Atspi.Role.PASSWORD_TEXT: _("pwd"), + + # Translators: short braille for the rolename of a popup menu. + Atspi.Role.POPUP_MENU: _("popmnu"), + + # Translators: short braille for the rolename of a progress bar. + Atspi.Role.PROGRESS_BAR: _("pgbar"), + + # Translators: short braille for the rolename of a push button. + Atspi.Role.PUSH_BUTTON: _("btn"), + + # Translators: short braille for the rolename of a radio button. + Atspi.Role.RADIO_BUTTON: _("radio"), + + # Translators: short braille for the rolename of a radio menu item. + Atspi.Role.RADIO_MENU_ITEM: _("rdmnuitm"), + + # Translators: short braille for the rolename of a root pane. + Atspi.Role.ROOT_PANE: _("rtpn"), + + # Translators: short braille for the rolename of a row header. + Atspi.Role.ROW_HEADER: _("rwhdr"), + + # Translators: short braille for the rolename of a scroll bar. + Atspi.Role.SCROLL_BAR: _("scbr"), + + # Translators: short braille for the rolename of a scroll pane. + Atspi.Role.SCROLL_PANE: _("scpn"), + + # Translators: short braille for the rolename of a section (e.g., in html). + Atspi.Role.SECTION: _("sctn"), + + # Translators: short braille for the rolename of a separator. + Atspi.Role.SEPARATOR: _("seprtr"), + + # Translators: short braille for the rolename of a slider. + Atspi.Role.SLIDER: _("sldr"), + + # Translators: short braille for the rolename of a split pane. + Atspi.Role.SPLIT_PANE: _("spltpn"), + + # Translators: short braille for the rolename of a spin button. + Atspi.Role.SPIN_BUTTON: _("spin"), + + # Translators: short braille for the rolename of a statusbar. + Atspi.Role.STATUS_BAR: _("statbr"), + + # Translators: short braille for the rolename of a table. + Atspi.Role.TABLE: _("tbl"), + + # Translators: short braille for the rolename of a table cell. + Atspi.Role.TABLE_CELL: _("cll"), + + # Translators: short braille for the rolename of a table column header. + Atspi.Role.TABLE_COLUMN_HEADER: _("colhdr"), + + # Translators: short braille for the rolename of a table row header. + Atspi.Role.TABLE_ROW_HEADER: _("rwhdr"), + + # Translators: short braille for the rolename of a tear off menu item. + Atspi.Role.TEAROFF_MENU_ITEM: _("tomnuitm"), + + # Translators: short braille for the rolename of a terminal. + Atspi.Role.TERMINAL: _("term"), + + # Translators: short braille for the rolename of a text entry field. + Atspi.Role.TEXT: _("txt"), + + # Translators: short braille for the rolename of a toggle button. + Atspi.Role.TOGGLE_BUTTON: _("tglbtn"), + + # Translators: short braille for the rolename of a toolbar. + Atspi.Role.TOOL_BAR: _("tbar"), + + # Translators: short braille for the rolename of a tooltip. + Atspi.Role.TOOL_TIP: _("tip"), + + # Translators: short braille for the rolename of a tree. + Atspi.Role.TREE: _("tre"), + + # Translators: short braille for the rolename of a tree table. + Atspi.Role.TREE_TABLE: _("trtbl"), + + # Translators: short braille for when the rolename of an object is unknown. + Atspi.Role.UNKNOWN: _("unk"), + + # Translators: short braille for the rolename of a viewport. + Atspi.Role.VIEWPORT: _("vwprt"), + + # Translators: short braille for the rolename of a window. + Atspi.Role.WINDOW: _("wnd"), + + # Translators: short braille for the rolename of a header. + Atspi.Role.HEADER: _("hdr"), + + # Translators: short braille for the rolename of a footer. + Atspi.Role.FOOTER: _("ftr"), + + # Translators: short braille for the rolename of a paragraph. + Atspi.Role.PARAGRAPH: _("para"), + + # Translators: short braille for the rolename of a application. + Atspi.Role.APPLICATION: _("app"), + + # Translators: short braille for the rolename of a autocomplete. + Atspi.Role.AUTOCOMPLETE: _("auto"), + + # Translators: short braille for the rolename of an editbar. + Atspi.Role.EDITBAR: _("edtbr"), + + # Translators: short braille for the rolename of an embedded component. + Atspi.Role.EMBEDDED: _("emb") +} diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brlmon.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brlmon.py new file mode 100644 index 0000000..6948b04 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brlmon.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides a graphical braille display, mainly for development tasks.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2011 The Cthulhu Team." +__license__ = "LGPL" + +import brlapi +from gi.repository import Gtk + +from . import cthulhu_state +from .input_event import BrailleEvent + +# Attribute/Selection mask strings: +# +DOT_7 = '\x40' # 01000000 +DOT_8 = '\x80' # 10000000 +DOTS_78 = '\xc0' # 11000000 + +class BrlDot(Gtk.Alignment): + """A single braille dot.""" + + MARKUP_NORMAL = '%s' + SYMBOL_LOWERED = '\u25CB' # '○' + SYMBOL_RAISED = '\u25CF' # '●' + + def __init__(self, dotNumber, isRaised=False): + """Create a new BrlDot. + + Arguments: + - dotNumber: an integer reflecting the location of the dot within + an 8-dot braille cell, using traditional braille dot values. + """ + + super().__init__() + if dotNumber in [1, 2, 3, 7]: + self.set(1.0, 0.5, 0.0, 0.0) + self.set_padding(3, 0, 0, 3) + else: + self.set(0.0, 0.5, 0.0, 0.0) + self.set_padding(3, 0, 3, 0) + + self.label = Gtk.Label() + self.add(self.label) + if isRaised: + self.raiseDot() + else: + self.lowerDot() + + def raiseDot(self): + self.set(0.5, 0.5, 0, 0) + self.label.set_markup(self.MARKUP_NORMAL % self.SYMBOL_RAISED) + + def lowerDot(self): + self.set(0.5, 0.5, 0, 0) + self.label.set_markup(self.MARKUP_NORMAL % self.SYMBOL_LOWERED) + +class BrlCell(Gtk.Button): + """A single graphical braille cell with cursor routing capability.""" + + MARKUP_NORMAL = '%s' + MARKUP_CURSOR_CELL = '%s' + + def __init__(self, position): + """Create a new BrlCell. + + Arguments: + - position: The location of the cell with respect to the monitor. + """ + + Gtk.Button.__init__(self) + self.set_size_request(30, 45) + self._position = position + self._displayedChar = Gtk.Label() + self._dot7 = BrlDot(7) + self._dot8 = BrlDot(8) + + grid = Gtk.Grid() + grid.attach(self._displayedChar, 0, 0, 2, 3) + grid.attach(self._dot7, 0, 3, 1, 1) + grid.attach(self._dot8, 1, 3, 1, 1) + self.add(grid) + + self.connect("clicked", self._onCellClicked) + + def _onCellClicked(self, widget): + """Callback for the 'clicked' signal on the push button. Synthesizes + a fake brlapi command to route the cursor to the current cell, similar + to what occurs when a user presses the cursor routing key on his/her + hardware braille display.""" + + if not cthulhu_state.activeScript: + return + + fakeKeyPress = {} + fakeKeyPress['command'] = brlapi.KEY_CMD_ROUTE + fakeKeyPress['argument'] = self._position + event = BrailleEvent(fakeKeyPress) + cthulhu_state.activeScript.processRoutingKey(event) + + def clear(self): + """Clears the braille cell.""" + + self._displayedChar.set_markup("") + self._dot7.lowerDot() + self._dot8.lowerDot() + + def display(self, char, mask=None, isCursorCell=False): + """Displays the specified character in the cell. + + Arguments: + - char: The character to display in the cell. + - isCursorCell: If True, the cursor/caret is at this cell and this + should be indicated visually. + """ + + if char == '&': + char = '&' + elif char == '<': + char = '<' + elif char == '\t': + char = '$t' + + markup = self.MARKUP_NORMAL + if isCursorCell: + markup = markup % self.MARKUP_CURSOR_CELL + self._displayedChar.set_markup(markup % char) + + if mask in [DOT_7, DOTS_78]: + self._dot7.raiseDot() + if mask in [DOT_8, DOTS_78]: + self._dot8.raiseDot() + +class BrlMon(Gtk.Window): + """Displays a GUI braille monitor that mirrors what would be displayed + by Cthulhu on a connected, configured, and enabled braille display. Cursor + routing functionality is emulated by each cell being a push button. + Panning and other functionality found on hardware braille displays will + be added.""" + + def __init__(self, numCells=32): + """Create a new BrlMon. + + Arguments: + - numCells: how many braille cells to make + """ + + super().__init__() + self.set_title("Braille Monitor") + + grid = Gtk.Grid() + self.add(grid) + + self.cells = [] + for i in range(numCells): + cell = BrlCell(i) + grid.attach(cell, i, 0, 1, 1) + self.cells.append(cell) + + self.set_resizable(False) + self.set_property("accept-focus", False) + self.set_skip_taskbar_hint(True) + self.set_skip_pager_hint(True) + + def clear(self): + """Clears the braille monitor display.""" + + for cell in self.cells: + cell.clear() + + def writeText(self, cursorCell, string, mask=None): + """Display the given text and highlight the given + cursor cell. A cursorCell of 0 means no cell has + the cursor. + + Arguments: + - cursorCell: 1-based index of cell with cursor + - string: len must be <= num cells. + """ + + self.clear() + length = min(len(string), len(self.cells)) + for i in range(length): + isCursorCell = i == cursorCell - 1 + try: + cellMask = mask[i] + except (IndexError, TypeError): + cellMask = None + self.cells[i].display(string[i], cellMask, isCursorCell) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brltablenames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brltablenames.py new file mode 100644 index 0000000..c46306d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/brltablenames.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Braille translation table names. These have been put in their own module +so that we can present them in the correct language when users change the +synthesizer language on the fly without having to reload a bunch of modules.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team" +__license__ = "LGPL" + +from .cthulhu_i18n import _ + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +CZ_CZ_G1 = _("Czech Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +ES_ES_G1 = _("Spanish Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +FR_CA_G2 = _("Canada French Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +FR_FR_G2 = _("France French Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +LV_LV_G1 = _("Latvian Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +NL_NL_G1 = _("Netherlands Dutch Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +NO_NO_G0 = _("Norwegian Grade 0") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +NO_NO_G1 = _("Norwegian Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +NO_NO_G2 = _("Norwegian Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +NO_NO_G3 = _("Norwegian Grade 3") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +PL_PL_G1 = _("Polish Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +PT_PT_G1 = _("Portuguese Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +SE_SE_G1 = _("Swedish Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +AR_AR_G1 = _("Arabic Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +CY_CY_G1 = _("Welsh Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +CY_CY_G2 = _("Welsh Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +DE_DE_G0 = _("German Grade 0") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +DE_DE_G1 = _("German Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +DE_DE_G2 = _("German Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +EN_GB_G2 = _("U.K. English Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +EN_GB_G1 = _("U.K. English Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +EN_US_G1 = _("U.S. English Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +EN_US_G2 = _("U.S. English Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +FR_CA_G1 = _("Canada French Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +FR_FR_G1 = _("France French Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +GR_GR_G1 = _("Greek Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +HI_IN_G1 = _("Hindi Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +HU_HU_8DOT = _("Hungarian 8 dot computer") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +HU_HU_G1 = _("Hungarian Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +HU_HU_G2 = _("Hungarian Grade 2") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +IT_IT_G1 = _("Italian Grade 1") + +# Translators: This is the name of a braille translation table. To learn more +# about braille translation tables, see http://en.wikipedia.org/wiki/Braille. +NL_BE_G1 = _("Belgium Dutch Grade 1") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/caret_navigation.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/caret_navigation.py new file mode 100644 index 0000000..53dc0a3 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/caret_navigation.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides an Cthulhu-controlled caret for text content.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013-2015 Igalia, S.L." +__license__ = "LGPL" + +from . import cmdnames +from . import debug +from . import input_event +from . import keybindings +from . import messages +from . import settings_manager + + +class CaretNavigation: + """Implements the caret navigation support available to scripts.""" + + def __init__(self, script): + if not (script and script.app): + msg = "CARET NAVIGATION: Caret navigation requires a script and app." + debug.printMessage(debug.LEVEL_INFO, msg) + + self._script = script + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + + def handles_navigation(self, handler): + """Returns True if handler is a navigation command.""" + + if handler not in self._handlers.values(): + return False + + if handler.function == self._toggle_enabled: + return False + + return True + + def get_bindings(self): + """Returns the caret-navigation keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the caret-navigation handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the caret-navigation input event handlers.""" + + handlers = {} + + if not (self._script and self._script.app): + return handlers + + handlers["toggle_enabled"] = \ + input_event.InputEventHandler( + self._toggle_enabled, + cmdnames.CARET_NAVIGATION_TOGGLE) + + handlers["next_character"] = \ + input_event.InputEventHandler( + self._next_character, + cmdnames.CARET_NAVIGATION_NEXT_CHAR) + + handlers["previous_character"] = \ + input_event.InputEventHandler( + self._previous_character, + cmdnames.CARET_NAVIGATION_PREV_CHAR) + + handlers["next_word"] = \ + input_event.InputEventHandler( + self._next_word, + cmdnames.CARET_NAVIGATION_NEXT_WORD) + + handlers["previous_word"] = \ + input_event.InputEventHandler( + self._previous_word, + cmdnames.CARET_NAVIGATION_PREV_WORD) + + handlers["next_line"] = \ + input_event.InputEventHandler( + self._next_line, + cmdnames.CARET_NAVIGATION_NEXT_LINE) + + handlers["previous_line"] = \ + input_event.InputEventHandler( + self._previous_line, + cmdnames.CARET_NAVIGATION_PREV_LINE) + + handlers["start_of_file"] = \ + input_event.InputEventHandler( + self._start_of_file, + cmdnames.CARET_NAVIGATION_FILE_START) + + handlers["end_of_file"] = \ + input_event.InputEventHandler( + self._end_of_file, + cmdnames.CARET_NAVIGATION_FILE_END) + + handlers["start_of_line"] = \ + input_event.InputEventHandler( + self._start_of_line, + cmdnames.CARET_NAVIGATION_LINE_START) + + handlers["end_of_line"] = \ + input_event.InputEventHandler( + self._end_of_line, + cmdnames.CARET_NAVIGATION_LINE_END) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the caret-navigation key bindings.""" + + bindings = keybindings.KeyBindings() + + if not (self._script and self._script.app): + return bindings + + bindings.add( + keybindings.KeyBinding( + "F12", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("toggle_enabled"))) + + bindings.add( + keybindings.KeyBinding( + "Right", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("next_character"))) + + bindings.add( + keybindings.KeyBinding( + "Left", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("previous_character"))) + + bindings.add( + keybindings.KeyBinding( + "Right", + keybindings.defaultModifierMask, + keybindings.CTRL_MODIFIER_MASK, + self._handlers.get("next_word"))) + + bindings.add( + keybindings.KeyBinding( + "Left", + keybindings.defaultModifierMask, + keybindings.CTRL_MODIFIER_MASK, + self._handlers.get("previous_word"))) + + bindings.add( + keybindings.KeyBinding( + "Down", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("next_line"))) + + bindings.add( + keybindings.KeyBinding( + "Up", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("previous_line"))) + + bindings.add( + keybindings.KeyBinding( + "End", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("end_of_line"))) + + bindings.add( + keybindings.KeyBinding( + "Home", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("start_of_line"))) + + bindings.add( + keybindings.KeyBinding( + "End", + keybindings.defaultModifierMask, + keybindings.CTRL_MODIFIER_MASK, + self._handlers.get("end_of_file"))) + + bindings.add( + keybindings.KeyBinding( + "Home", + keybindings.defaultModifierMask, + keybindings.CTRL_MODIFIER_MASK, + self._handlers.get("start_of_file"))) + + return bindings + + @staticmethod + def _toggle_enabled(script, event): + """Toggles caret navigation.""" + + if not event: + return False + + _settings_manager = settings_manager.getManager() + enabled = not _settings_manager.getSetting('caretNavigationEnabled') + if enabled: + string = messages.CARET_CONTROL_CTHULHU + else: + string = messages.CARET_CONTROL_APP + + script.presentMessage(string) + _settings_manager.setSetting('caretNavigationEnabled', enabled) + return True + + @staticmethod + def _next_character(script, event): + """Moves to the next character.""" + + if not event: + return False + + obj, offset = script.utilities.nextContext() + if not obj: + return False + + script.utilities.setCaretPosition(obj, offset) + script.updateBraille(obj) + script.sayCharacter(obj) + return True + + @staticmethod + def _previous_character(script, event): + """Moves to the previous character.""" + + if not event: + return False + + obj, offset = script.utilities.previousContext() + if not obj: + return False + + script.utilities.setCaretPosition(obj, offset) + script.updateBraille(obj) + script.sayCharacter(obj) + return True + + @staticmethod + def _next_word(script, event): + """Moves to the next word.""" + + if not event: + return False + + obj, offset = script.utilities.nextContext(skipSpace=True) + contents = script.utilities.getWordContentsAtOffset(obj, offset) + if not contents: + return False + + obj, end, string = contents[-1][0], contents[-1][2], contents[-1][3] + if string and string[-1].isspace(): + end -= 1 + + script.utilities.setCaretPosition(obj, end) + script.updateBraille(obj) + script.sayWord(obj) + return True + + @staticmethod + def _previous_word(script, event): + """Moves to the previous word.""" + + if not event: + return False + + obj, offset = script.utilities.previousContext(skipSpace=True) + contents = script.utilities.getWordContentsAtOffset(obj, offset) + if not contents: + return False + + obj, start = contents[0][0], contents[0][1] + script.utilities.setCaretPosition(obj, start) + script.updateBraille(obj) + script.sayWord(obj) + return True + + @staticmethod + def _next_line(script, event): + """Moves to the next line.""" + + if not event: + return False + + if script.inSayAll(): + _settings_manager = settings_manager.getManager() + if _settings_manager.getSetting('rewindAndFastForwardInSayAll'): + msg = "CARET NAVIGATION: inSayAll and rewindAndFastforwardInSayAll is enabled" + debug.printMessage(debug.LEVEL_INFO, msg) + return True + + obj, offset = script.utilities.getCaretContext() + line = script.utilities.getLineContentsAtOffset(obj, offset) + if not (line and line[0]): + return False + + contents = script.utilities.getNextLineContents() + if not contents: + return False + + obj, start = contents[0][0], contents[0][1] + script.utilities.setCaretPosition(obj, start) + script.speakContents(contents, priorObj=line[-1][0]) + script.displayContents(contents) + return True + + @staticmethod + def _previous_line(script, event): + """Moves to the previous line.""" + + if not event: + return False + + if script.inSayAll(): + _settings_manager = settings_manager.getManager() + if _settings_manager.getSetting('rewindAndFastForwardInSayAll'): + msg = "CARET NAVIGATION: inSayAll and rewindAndFastforwardInSayAll is enabled" + debug.printMessage(debug.LEVEL_INFO, msg) + return True + + + contents = script.utilities.getPreviousLineContents() + if not contents: + return False + + obj, start = contents[0][0], contents[0][1] + script.utilities.setCaretPosition(obj, start) + script.speakContents(contents) + script.displayContents(contents) + return True + + @staticmethod + def _start_of_line(script, event): + """Moves to the start of the line.""" + + if not event: + return False + + obj, offset = script.utilities.getCaretContext() + line = script.utilities.getLineContentsAtOffset(obj, offset) + if not (line and line[0]): + return False + + obj, start = line[0][0], line[0][1] + script.utilities.setCaretPosition(obj, start) + script.sayCharacter(obj) + script.displayContents(line) + return True + + @staticmethod + def _end_of_line(script, event): + """Moves to the end of the line.""" + + if not event: + return False + + obj, offset = script.utilities.getCaretContext() + line = script.utilities.getLineContentsAtOffset(obj, offset) + if not (line and line[0]): + return False + + obj, end, string = line[-1][0], line[-1][2], line[-1][3] + if string.strip() and string[-1].isspace(): + end -= 1 + + script.utilities.setCaretPosition(obj, end) + script.sayCharacter(obj) + script.displayContents(line) + return True + + @staticmethod + def _start_of_file(script, event): + """Moves to the start of the file.""" + + if not event: + return False + + document = script.utilities.documentFrame() + obj, offset = script.utilities.findFirstCaretContext(document, 0) + contents = script.utilities.getLineContentsAtOffset(obj, offset) + if not contents: + return False + + obj, offset = contents[0][0], contents[0][1] + script.utilities.setCaretPosition(obj, offset) + script.speakContents(contents) + script.displayContents(contents) + return True + + @staticmethod + def _end_of_file(script, event): + """Moves to the end of the file.""" + + if not event: + return False + + document = script.utilities.documentFrame() + tokens = ["CARET NAVIGATION: Go to end of", document] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + obj = script.utilities.getLastObjectInDocument(document) + tokens = ["CARET NAVIGATION: Last object in", document, "is", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + offset = 0 + text = script.utilities.queryNonEmptyText(obj) + if text: + offset = text.characterCount - 1 + + while obj: + lastobj, lastoffset = script.utilities.nextContext(obj, offset) + if not lastobj: + break + obj, offset = lastobj, lastoffset + + contents = script.utilities.getLineContentsAtOffset(obj, offset) + if not contents: + return False + + obj, offset = contents[-1][0], contents[-1][2] + script.utilities.setCaretPosition(obj, offset) + script.speakContents(contents) + script.displayContents(contents) + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chat.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chat.py new file mode 100644 index 0000000..52c01ce --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chat.py @@ -0,0 +1,935 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Implements generic chat support.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010-2011 The Cthulhu Team" +__license__ = "LGPL" + +from . import cmdnames +from . import debug +from . import guilabels +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu_state +from . import settings +from . import settings_manager +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +############################################################################# +# # +# Ring List. A fixed size circular list by Flavio Catalani # +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/435902 # +# # +# Included here to keep track of conversation histories. # +# # +############################################################################# + +class RingList: + def __init__(self, length): + self.__data__ = [] + self.__full__ = 0 + self.__max__ = length + self.__cur__ = 0 + + def append(self, x): + if self.__full__ == 1: + for i in range (0, self.__cur__ - 1): + self.__data__[i] = self.__data__[i + 1] + self.__data__[self.__cur__ - 1] = x + else: + self.__data__.append(x) + self.__cur__ += 1 + if self.__cur__ == self.__max__: + self.__full__ = 1 + + def get(self): + return self.__data__ + + def remove(self): + if (self.__cur__ > 0): + del self.__data__[self.__cur__ - 1] + self.__cur__ -= 1 + + def size(self): + return self.__cur__ + + def maxsize(self): + return self.__max__ + + def __str__(self): + return ''.join(self.__data__) + +############################################################################# +# # +# Conversation # +# # +############################################################################# + +class Conversation: + + # The number of messages to keep in the history + # + MESSAGE_LIST_LENGTH = 9 + + def __init__(self, name, accHistory, inputArea=None): + + """Creates a new instance of the Conversation class. + + Arguments: + - name: the chatroom/conversation name + - accHistory: the accessible which holds the conversation history + - inputArea: the editable text object for this conversation. + """ + + self.name = name + self.accHistory = accHistory + self.inputArea = inputArea + + # A cyclic list to hold the chat room history for this conversation + # + self._messageHistory = RingList(Conversation.MESSAGE_LIST_LENGTH) + + # Initially populate the cyclic lists with empty strings. + # + i = 0 + while i < self._messageHistory.maxsize(): + self.addMessage("") + i += 1 + + # Keep track of the last typing status because some platforms (e.g. + # MSN) seem to issue the status constantly and even though it has + # not changed. + # + self._typingStatus = "" + + def addMessage(self, message): + """Adds the current message to the message history. + + Arguments: + - message: A string containing the message to add + """ + + self._messageHistory.append(message) + + def getNthMessage(self, messageNumber): + """Returns the specified message from the message history. + + Arguments: + - messageNumber: the index of the message to get. + """ + + messages = self._messageHistory.get() + + return messages[messageNumber] + + def getTypingStatus(self): + """Returns the typing status of the buddy in this conversation.""" + + return self._typingStatus + + def setTypingStatus(self, status): + """Sets the typing status of the buddy in this conversation. + + Arguments: + - status: a string describing the current status. + """ + + self._typingStatus = status + +############################################################################# +# # +# ConversationList # +# # +############################################################################# + +class ConversationList: + + def __init__(self, messageListLength): + + """Creates a new instance of the ConversationList class. + + Arguments: + - messageListLength: the size of the message history to keep. + """ + + self.conversations = [] + + # A cyclic list to hold the most recent (messageListLength) previous + # messages for all conversations in the ConversationList. + # + self._messageHistory = RingList(messageListLength) + + # A corresponding cyclic list to hold the name of the conversation + # associated with each message in the messageHistory. + # + self._roomHistory = RingList(messageListLength) + + # Initially populate the cyclic lists with empty strings. + # + i = 0 + while i < self._messageHistory.maxsize(): + self.addMessage("", None) + i += 1 + + def addMessage(self, message, conversation): + """Adds the current message to the message history. + + Arguments: + - message: A string containing the message to add + - conversation: The instance of the Conversation class with which + the message is associated + """ + + if not conversation: + name = "" + else: + if not self.hasConversation(conversation): + self.addConversation(conversation) + name = conversation.name + + self._messageHistory.append(message) + self._roomHistory.append(name) + + def getNthMessageAndName(self, messageNumber): + """Returns a list containing the specified message from the message + history and the name of the chatroom/conversation associated with + that message. + + Arguments: + - messageNumber: the index of the message to get. + """ + + messages = self._messageHistory.get() + rooms = self._roomHistory.get() + + return messages[messageNumber], rooms[messageNumber] + + def hasConversation(self, conversation): + """Returns True if we know about this conversation. + + Arguments: + - conversation: the conversation of interest + """ + + return conversation in self.conversations + + def getNConversations(self): + """Returns the number of conversations we currently know about.""" + + return len(self.conversations) + + def addConversation(self, conversation): + """Adds conversation to the list of conversations. + + Arguments: + - conversation: the conversation to add + """ + + self.conversations.append(conversation) + + def removeConversation(self, conversation): + """Removes conversation from the list of conversations. + + Arguments: + - conversation: the conversation to remove + + Returns True if conversation was successfully removed. + """ + + # TODO - JD: In the Pidgin script, I do not believe we handle the + # case where a conversation window is closed. I *think* it remains + # in the overall chat history. What do we want to do in that case? + # I would assume that we'd want to remove it.... So here's a method + # to do so. Nothing in the Chat class uses it yet. + # + try: + self.conversations.remove(conversation) + except Exception: + return False + else: + return True + +############################################################################# +# # +# Chat # +# # +############################################################################# + +class Chat: + """This class implements the chat functionality which is available to + scripts. + """ + + def __init__(self, script, buddyListAncestries): + """Creates an instance of the Chat class. + + Arguments: + - script: the script with which this instance is associated. + - buddyListAncestries: a list of lists of roles beginning + with the object serving as the actual buddy list (e.g. + ROLE_TREE_TABLE) and ending with the top level object (e.g. + ROLE_FRAME). + """ + + self._script = script + self._buddyListAncestries = buddyListAncestries + + # Keybindings to provide conversation message history. The message + # review order will be based on the index within the list. Thus F1 + # is associated with the most recent message, F2 the message before + # that, and so on. A script could override this. Setting messageKeys + # to ["a", "b", "c" ... ] will cause "a" to be associated with the + # most recent message, "b" to be associated with the message before + # that, etc. Scripts can also override the messageKeyModifier. + # + self.messageKeys = \ + ["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"] + self.messageKeyModifier = keybindings.CTHULHU_MODIFIER_MASK + self.inputEventHandlers = {} + self.setupInputEventHandlers() + self.keyBindings = self.getKeyBindings() + + # The length of the message history will be based on how many keys + # are bound to the task of providing it. + # + self.messageListLength = len(self.messageKeys) + self._conversationList = ConversationList(self.messageListLength) + + self.focusedChannelRadioButton = None + self.allChannelsRadioButton = None + self.allMessagesRadioButton = None + self.buddyTypingCheckButton = None + self.chatRoomHistoriesCheckButton = None + self.speakNameCheckButton = None + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for chat functions which + will be used by the script associated with this chat instance.""" + + self.inputEventHandlers["togglePrefixHandler"] = \ + input_event.InputEventHandler( + self.togglePrefix, + cmdnames.CHAT_TOGGLE_ROOM_NAME_PREFIX) + + self.inputEventHandlers["toggleBuddyTypingHandler"] = \ + input_event.InputEventHandler( + self.toggleBuddyTyping, + cmdnames.CHAT_TOGGLE_BUDDY_TYPING) + + self.inputEventHandlers["toggleMessageHistoriesHandler"] = \ + input_event.InputEventHandler( + self.toggleMessageHistories, + cmdnames.CHAT_TOGGLE_MESSAGE_HISTORIES) + + self.inputEventHandlers["reviewMessage"] = \ + input_event.InputEventHandler( + self.readPreviousMessage, + cmdnames.CHAT_PREVIOUS_MESSAGE) + + return + + def getKeyBindings(self): + """Defines the chat-related key bindings which will be used by + the script associated with this chat instance. + + Returns: an instance of keybindings.KeyBindings. + """ + + keyBindings = keybindings.KeyBindings() + + keyBindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self.inputEventHandlers["togglePrefixHandler"])) + + keyBindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self.inputEventHandlers["toggleBuddyTypingHandler"])) + + keyBindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self.inputEventHandlers["toggleMessageHistoriesHandler"])) + + for messageKey in self.messageKeys: + keyBindings.add( + keybindings.KeyBinding( + messageKey, + self.messageKeyModifier, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["reviewMessage"])) + + return keyBindings + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application. """ + + from gi.repository import Gtk + + grid = Gtk.Grid() + grid.set_border_width(12) + + label = guilabels.CHAT_SPEAK_ROOM_NAME + value = _settingsManager.getSetting('chatSpeakRoomName') + self.speakNameCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self.speakNameCheckButton.set_active(value) + grid.attach(self.speakNameCheckButton, 0, 0, 1, 1) + + label = guilabels.CHAT_ANNOUNCE_BUDDY_TYPING + value = _settingsManager.getSetting('chatAnnounceBuddyTyping') + self.buddyTypingCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self.buddyTypingCheckButton.set_active(value) + grid.attach(self.buddyTypingCheckButton, 0, 1, 1, 1) + + label = guilabels.CHAT_SEPARATE_MESSAGE_HISTORIES + value = _settingsManager.getSetting('chatRoomHistories') + self.chatRoomHistoriesCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.chatRoomHistoriesCheckButton.set_active(value) + grid.attach(self.chatRoomHistoriesCheckButton, 0, 2, 1, 1) + + messagesFrame = Gtk.Frame() + grid.attach(messagesFrame, 0, 3, 1, 1) + label = Gtk.Label(f"{guilabels.CHAT_SPEAK_MESSAGES_FROM}") + label.set_use_markup(True) + messagesFrame.set_label_widget(label) + + messagesAlignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) + messagesAlignment.set_padding(0, 0, 12, 0) + messagesFrame.add(messagesAlignment) + messagesGrid = Gtk.Grid() + messagesAlignment.add(messagesGrid) + + value = _settingsManager.getSetting('chatMessageVerbosity') + + label = guilabels.CHAT_SPEAK_MESSAGES_ALL + rb1 = Gtk.RadioButton.new_with_mnemonic(None, label) + rb1.set_active(value == settings.CHAT_SPEAK_ALL) + self.allMessagesRadioButton = rb1 + messagesGrid.attach(self.allMessagesRadioButton, 0, 0, 1, 1) + + label = guilabels.CHAT_SPEAK_MESSAGES_ACTIVE + rb2 = Gtk.RadioButton.new_with_mnemonic(None, label) + rb2.join_group(rb1) + rb2.set_active(value == settings.CHAT_SPEAK_FOCUSED_CHANNEL) + self.focusedChannelRadioButton = rb2 + messagesGrid.attach(self.focusedChannelRadioButton, 0, 1, 1, 1) + + label = guilabels.CHAT_SPEAK_MESSAGES_ALL_IF_FOCUSED % \ + AXObject.get_name(self._script.app) + rb3 = Gtk.RadioButton.new_with_mnemonic(None, label) + rb3.join_group(rb1) + rb3.set_active(value == settings.CHAT_SPEAK_ALL_IF_FOCUSED) + self.allChannelsRadioButton = rb3 + messagesGrid.attach(self.allChannelsRadioButton, 0, 2, 1, 1) + + grid.show_all() + + return grid + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + if self.allChannelsRadioButton.get_active(): + verbosity = settings.CHAT_SPEAK_ALL_IF_FOCUSED + elif self.focusedChannelRadioButton.get_active(): + verbosity = settings.CHAT_SPEAK_FOCUSED_CHANNEL + else: + verbosity = settings.CHAT_SPEAK_ALL + + return { + 'chatMessageVerbosity': verbosity, + 'chatSpeakRoomName': self.speakNameCheckButton.get_active(), + 'chatAnnounceBuddyTyping': self.buddyTypingCheckButton.get_active(), + 'chatRoomHistories': self.chatRoomHistoriesCheckButton.get_active(), + } + + ######################################################################## + # # + # InputEvent handlers and supporting utilities # + # # + ######################################################################## + + def togglePrefix(self, script, inputEvent): + """ Toggle whether we prefix chat room messages with the name of + the chat room. + + Arguments: + - script: the script associated with this event + - inputEvent: if not None, the input event that caused this action. + """ + + line = messages.CHAT_ROOM_NAME_PREFIX_ON + speakRoomName = _settingsManager.getSetting('chatSpeakRoomName') + _settingsManager.setSetting('chatSpeakRoomName', not speakRoomName) + if speakRoomName: + line = messages.CHAT_ROOM_NAME_PREFIX_OFF + self._script.presentMessage(line) + + return True + + def toggleBuddyTyping(self, script, inputEvent): + """ Toggle whether we announce when our buddies are typing a message. + + Arguments: + - script: the script associated with this event + - inputEvent: if not None, the input event that caused this action. + """ + + line = messages.CHAT_BUDDY_TYPING_ON + announceTyping = _settingsManager.getSetting('chatAnnounceBuddyTyping') + _settingsManager.setSetting( + 'chatAnnounceBuddyTyping', not announceTyping) + if announceTyping: + line = messages.CHAT_BUDDY_TYPING_OFF + self._script.presentMessage(line) + + return True + + def toggleMessageHistories(self, script, inputEvent): + """ Toggle whether we provide chat room specific message histories. + + Arguments: + - script: the script associated with this event + - inputEvent: if not None, the input event that caused this action. + """ + + line = messages.CHAT_SEPARATE_HISTORIES_ON + roomHistories = _settingsManager.getSetting('chatRoomHistories') + _settingsManager.setSetting('chatRoomHistories', not roomHistories) + if roomHistories: + line = messages.CHAT_SEPARATE_HISTORIES_OFF + self._script.presentMessage(line) + + return True + + def readPreviousMessage(self, script, inputEvent=None, index=0): + """ Speak/braille a previous chat room message. + + Arguments: + - script: the script associated with this event + - inputEvent: if not None, the input event that caused this action. + - index: The index of the message to read -- by default, the most + recent message. If we get an inputEvent, however, the value of + index is ignored and the index of the event_string with respect + to self.messageKeys is used instead. + """ + + try: + index = self.messageKeys.index(inputEvent.event_string) + except Exception: + pass + + messageNumber = self.messageListLength - (index + 1) + message, chatRoomName = None, None + + if _settingsManager.getSetting('chatRoomHistories'): + conversation = self.getConversation(cthulhu_state.locusOfFocus) + if conversation: + message = conversation.getNthMessage(messageNumber) + chatRoomName = conversation.name + else: + message, chatRoomName = \ + self._conversationList.getNthMessageAndName(messageNumber) + + if message and chatRoomName: + self.utterMessage(chatRoomName, message, True) + + def utterMessage(self, chatRoomName, message, focused=True): + """ Speak/braille a chat room message. + + Arguments: + - chatRoomName: name of the chat room this message came from + - message: the chat room message + - focused: whether or not the current chatroom has focus. Defaults + to True so that we can use this method to present chat history + as well as incoming messages. + """ + + # Only speak/braille the new message if it matches how the user + # wants chat messages spoken. + # + verbosity = _settingsManager.getAppSetting(self._script.app, 'chatMessageVerbosity') + if cthulhu_state.activeScript.name != self._script.name \ + and verbosity == settings.CHAT_SPEAK_ALL_IF_FOCUSED: + return + elif not focused and verbosity == settings.CHAT_SPEAK_FOCUSED_CHANNEL: + return + + text = "" + if chatRoomName and \ + _settingsManager.getAppSetting(self._script.app, 'chatSpeakRoomName'): + text = messages.CHAT_MESSAGE_FROM_ROOM % chatRoomName + + if not settings.presentChatRoomLast: + text = self._script.utilities.appendString(text, message) + else: + text = self._script.utilities.appendString(message, text) + + if len(text.strip()): + voice = self._script.speechGenerator.voice(string=text) + self._script.speakMessage(text, voice=voice) + self._script.displayBrailleMessage(text) + + def getMessageFromEvent(self, event): + """Get the actual displayed message. This will almost always be the + unaltered any_data from an event of type object:text-changed:insert. + + Arguments: + - event: the Event from which to take the text. + + Returns the string which should be presented as the newly-inserted + text. (Things like chatroom name prefacing get handled elsewhere.) + """ + + return event.any_data + + def presentInsertedText(self, event): + """Gives the Chat class an opportunity to present the text from the + text inserted Event. + + Arguments: + - event: the text inserted Event + + Returns True if we handled this event here; otherwise False, which + tells the associated script that is not a chat event that requires + custom handling. + """ + + if not event \ + or not event.type.startswith("object:text-changed:insert") \ + or not event.any_data: + return False + + if self.isGenericTextObject(event.source): + # The script should handle non-chat specific text areas (e.g., + # adding a new account). + # + return False + + elif self.isInBuddyList(event.source): + # These are status changes. What the Pidgin script currently + # does for these is ignore them. It might be nice to add + # some options to allow the user to customize what status + # changes are presented. But for now, we'll ignore them + # across the board. + # + return True + + elif self.isTypingStatusChangedEvent(event): + self.presentTypingStatusChange(event, event.any_data) + return True + + elif self.isChatRoomMsg(event.source): + # We always automatically go back to focus tracking mode when + # someone sends us a message. + # + if self._script.flatReviewPresenter.is_active(): + self._script.flatReviewPresenter.quit() + + if self.isNewConversation(event.source): + name = self.getChatRoomName(event.source) + conversation = Conversation(name, event.source) + else: + conversation = self.getConversation(event.source) + name = conversation.name + message = self.getMessageFromEvent(event).strip("\n") + if message: + self.addMessageToHistory(message, conversation) + + # The user may or may not want us to present this message. Also, + # don't speak the name if it's the focused chat. + # + focused = self.isFocusedChat(event.source) + if focused: + name = "" + if message: + self.utterMessage(name, message, focused) + return True + + elif self.isAutoCompletedTextEvent(event): + text = event.any_data + voice = self._script.speechGenerator.voice(string=text) + self._script.speakMessage(text, voice=voice) + return True + + return False + + def presentTypingStatusChange(self, event, status): + """Presents a change in typing status for the current conversation + if the status has indeed changed and if the user wants to hear it. + + Arguments: + - event: the accessible Event + - status: a string containing the status change + + Returns True if we spoke the change; False otherwise + """ + + if _settingsManager.getSetting('chatAnnounceBuddyTyping'): + conversation = self.getConversation(event.source) + if conversation and (status != conversation.getTypingStatus()): + voice = self._script.speechGenerator.voice(string=status) + self._script.speakMessage(status, voice=voice) + conversation.setTypingStatus(status) + return True + + return False + + def addMessageToHistory(self, message, conversation): + """Adds message to both the individual conversation's history + as well as to the complete history stored in our conversation + list. + + Arguments: + - message: a string containing the message to be added + - conversation: the instance of the Conversation class to which + this message belongs + """ + + conversation.addMessage(message) + self._conversationList.addMessage(message, conversation) + + ######################################################################## + # # + # Convenience methods for identifying, locating different accessibles # + # # + ######################################################################## + + def isGenericTextObject(self, obj): + """Returns True if the given accessible seems to be something + unrelated to the custom handling we're attempting to do here. + + Arguments: + - obj: the accessible object to examine. + """ + + return AXUtilities.is_editable(obj) and AXUtilities.is_single_line(obj) + + def isBuddyList(self, obj): + """Returns True if obj is the list of buddies in the buddy list + window. Note that this method relies upon a hierarchical check, + using a list of hierarchies provided by the script. Scripts + which have more reliable means of identifying the buddy list + can override this method. + + Arguments: + - obj: the accessible being examined + """ + + if obj is None: + return False + + for roleList in self._buddyListAncestries: + if self._script.utilities.hasMatchingHierarchy(obj, roleList): + return True + + return False + + def isInBuddyList(self, obj, includeList=True): + """Returns True if obj is, or is inside of, the buddy list. + + Arguments: + - obj: the accessible being examined + - includeList: whether or not the list itself should be + considered "in" the buddy list. + """ + + if includeList and self.isBuddyList(obj): + return True + + for roleList in self._buddyListAncestries: + role = roleList[0] + candidate = AXObject.find_ancestor(obj, lambda x: AXObject.get_role(x) == role) + if self.isBuddyList(candidate): + return True + + return False + + def isNewConversation(self, obj): + """Returns True if the given accessible is the chat history + associated with a new conversation. + + Arguments: + - obj: the accessible object to examine. + """ + + conversation = self.getConversation(obj) + return not self._conversationList.hasConversation(conversation) + + def getConversation(self, obj): + """Attempts to locate the conversation associated with obj. + + Arguments: + - obj: the accessible of interest + + Returns the conversation if found; None otherwise + """ + + if not obj: + return None + + name = "" + # TODO - JD: If we have multiple chats going on and those + # chats have the same name, and we're in the input area, + # this approach will fail. What I should probably do instead + # is, upon creation of a new conversation, figure out where + # the input area is and save it. For now, I just want to get + # things working. And people should not be in multiple chat + # rooms with identical names anyway. :-) + # + if (AXUtilities.is_text(obj) or AXObject.is_entry(obj)) \ + and AXUtilities.is_editable(obj): + name = self.getChatRoomName(obj) + + for conversation in self._conversationList.conversations: + if name: + if name == conversation.name: + return conversation + # Doing an equality check seems to be preferable here to + # utilities.isSameObject as a result of false positives. + # + elif obj == conversation.accHistory: + return conversation + + return None + + def isChatRoomMsg(self, obj): + """Returns True if the given accessible is the text object for + associated with a chat room conversation. + + Arguments: + - obj: the accessible object to examine. + """ + + if AXUtilities.is_text(obj) and AXUtilities.is_scroll_pane(AXObject.get_parent(obj)): + return not AXUtilities.is_editable(obj) and AXUtilities.is_multi_line(obj) + return False + + def isFocusedChat(self, obj): + """Returns True if we plan to treat this chat as focused for + the purpose of deciding whether or not a message should be + presented to the user. + + Arguments: + - obj: the accessible object to examine. + """ + + if AXUtilities.is_showing(obj): + active = self._script.utilities.topLevelObjectIsActiveAndCurrent(obj) + tokens = ["INFO:", obj, "'s window is focused chat:", active] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return active + + tokens = ["INFO:", obj, "is not focused chat (not showing)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + def getChatRoomName(self, obj): + """Attempts to find the name of the current chat room. + + Arguments: + - obj: The accessible of interest + + Returns a string containing what we think is the chat room name. + """ + + # Most of the time, it seems that the name can be found in the + # page tab which is the ancestor of the chat history. Failing + # that, we'll look at the frame name. Failing that, scripts + # should override this method. :-) + # + def pred(x): + return AXUtilities.is_page_tab(x) or AXUtilities.is_frame(x) + + ancestor = AXObject.find_ancestor(obj, pred) + name = "" + try: + text = self._script.utilities.displayedText(ancestor) + if text.lower().strip() != self._script.name.lower().strip(): + name = text + except Exception: + pass + + # Some applications don't trash their page tab list when there is + # only one active chat, but instead they remove the text or hide + # the item. Therefore, we'll give it one more shot. + # + if not name: + ancestor = AXObject.find_ancestor(obj, AXUtilities.is_frame) + try: + text = self._script.utilities.displayedText(ancestor) + if text.lower().strip() != self._script.name.lower().strip(): + name = text + except Exception: + pass + + return name + + def isAutoCompletedTextEvent(self, event): + """Returns True if event is associated with text being autocompleted. + + Arguments: + - event: the accessible event being examined + """ + + if not AXUtilities.is_text(event.source): + return False + + lastKey, mods = self._script.utilities.lastKeyAndModifiers() + if lastKey == "Tab" and event.any_data and event.any_data != "\t": + return True + + return False + + def isTypingStatusChangedEvent(self, event): + """Returns True if event is associated with a change in typing status. + + Arguments: + - event: the accessible event being examined + """ + + # TODO - JD: I still need to figure this one out. Pidgin seems to + # no longer be presenting this change in the conversation history + # as it was doing before. And I'm not yet sure what other apps do. + # In the meantime, scripts can override this. + # + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chnames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chnames.py new file mode 100644 index 0000000..3da83d5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/chnames.py @@ -0,0 +1,822 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides getCharacterName that maps punctuation marks and other +individual characters into localized words.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +from . import mathsymbols +from . import cthulhu_state +from .cthulhu_i18n import _ + +# chnames is a dictionary where the keys represent a unicode character +# and the values represent the common term used for the character. +# +chnames = {} + +# Translators: this is the spoken word for the space character +# +chnames[" "] = _("space") + +# Translators: this is the spoken word for the newline character +# +chnames["\n"] = _("newline") + +# Translators: this is the spoken word for the tab character +# +chnames["\t"] = _("tab") + +# Translators: this is the spoken word for the character '!' (U+0021) +# +chnames["!"] = _("exclaim") + +# Translators: this is the spoken word for the character '"' (U+0022) +# +chnames["\""] = _("quote") + +# Translators: this is the spoken word for the character '#' (U+0023) +# +chnames["#"] = _("number") + +# Translators: this is the spoken word for the character '$' (U+0024) +# +chnames["$"] = _("dollar") + +# Translators: this is the spoken word for the character '%' (U+0025) +# +chnames["%"] = _("percent") + +# Translators: this is the spoken word for the character '&' (U+0026) +# +chnames["&"] = _("and") + +# Translators: this is the spoken word for the character ''' (U+0027) +# +chnames["'"] = _("apostrophe") + +# Translators: this is the spoken word for the character '(' (U+0028) +# +chnames["("] = _("left paren") + +# Translators: this is the spoken word for the character ')' (U+0029) +# +chnames[")"] = _("right paren") + +# Translators: this is the spoken word for the character '*' (U+002a) +# +chnames["*"] = _("star") + +# Translators: this is the spoken word for the character '+' (U+002b) +# +chnames["+"] = _("plus") + +# Translators: this is the spoken word for the character ',' (U+002c) +# +chnames[","] = _("comma") + +# Translators: this is the spoken word for the character '-' (U+002d) +# +chnames["-"] = _("dash") + +# Translators: this is the spoken word for the character '.' (U+002e) +# +chnames["."] = _("dot") + +# Translators: this is the spoken word for the character '/' (U+002f) +# +chnames["/"] = _("slash") + +# Translators: this is the spoken word for the character ':' (U+003a) +# +chnames[":"] = _("colon") + +# Translators: this is the spoken word for the character ';' (U+003b) +# +chnames[";"] = _("semicolon") + +# Translators: this is the spoken word for the character '< ' (U+003c) +# +chnames["<"] = _("less") + +# Translators: this is the spoken word for the character '=' (U+003d) +# +chnames["="] = _("equals") + +# Translators: this is the spoken word for the character '> ' (U+003e) +# +chnames[">"] = _("greater") + +# Translators: this is the spoken word for the character '?' (U+003f) +# +chnames["?"] = _("question") + +# Translators: this is the spoken word for the character '@' (U+0040) +# +chnames["@"] = _("at") + +# Translators: this is the spoken word for the character '[' (U+005b) +# +chnames["["] = _("left bracket") + +# Translators: this is the spoken word for the character '\' (U+005c) +# +chnames["\\"] = _("backslash") + +# Translators: this is the spoken word for the character ']' (U+005d) +# +chnames["]"] = _("right bracket") + +# Translators: this is the spoken word for the character '^' (U+005e) +# +chnames["^"] = _("caret") + +# Translators: this is the spoken word for the character '_' (U+005f) +# +chnames["_"] = _("underline") + +# Translators: this is the spoken word for the character '`' (U+0060) +# +chnames["`"] = _("grave") + +# Translators: this is the spoken word for the character '{' (U+007b) +# +chnames["{"] = _("left brace") + +# Translators: this is the spoken word for the character '|' (U+007c) +# +chnames["|"] = _("vertical bar") + +# Translators: this is the spoken word for the character '}' (U+007d) +# +chnames["}"] = _("right brace") + +# Translators: this is the spoken word for the character '~' (U+007e) +# +chnames["~"] = _("tilde") + +# Translators: this is the spoken character for the no break space +# character (e.g., " " in HTML -- U+00a0) +# +chnames['\u00a0'] = _("no break space") + +# Translators: this is the spoken word for the character '¡' (U+00a1) +# +chnames['\u00a1'] = _("inverted exclamation point") + +# Translators: this is the spoken word for the character '¢' (U+00a2) +# +chnames['\u00a2'] = _("cents") + +# Translators: this is the spoken word for the character '£' (U+00a3) +# +chnames['\u00a3'] = _("pounds") + +# Translators: this is the spoken word for the character '¤' (U+00a4) +# +chnames['\u00a4'] = _("currency sign") + +# Translators: this is the spoken word for the character '¥' (U+00a5) +# +chnames['\u00a5'] = _("yen") + +# Translators: this is the spoken word for the character '¦' (U+00a6) +# +chnames['\u00a6'] = _("broken bar") + +# Translators: this is the spoken word for the character '§' (U+00a7) +# +chnames['\u00a7'] = _("section") + +# Translators: this is the spoken word for the character '¨' (U+00a8) +# +chnames['\u00a8'] = _("diaeresis") + +# Translators: this is the spoken word for the character '©' (U+00a9) +# +chnames['\u00a9'] = _("copyright") + +# Translators: this is the spoken word for the character 'ª' (U+00aa) +# +chnames['\u00aa'] = _("superscript a") + +# Translators: this is the spoken word for the character '«' (U+00ab) +# +chnames['\u00ab'] = _("left double angle bracket") + +# Translators: this is the spoken word for the character '¬' (U+00ac) +# +chnames['\u00ac'] = _("logical not") + +# Translators: this is the spoken word for the character '­' (U+00ad) +# +chnames['\u00ad'] = _("soft hyphen") + +# Translators: this is the spoken word for the character '®' (U+00ae) +# +chnames['\u00ae'] = _("registered") + +# Translators: this is the spoken word for the character '¯' (U+00af) +# +chnames['\u00af'] = _("macron") + +# Translators: this is the spoken word for the character '°' (U+00b0) +# +chnames['\u00b0'] = _("degrees") + +# Translators: this is the spoken word for the character '±' (U+00b1) +# +chnames['\u00b1'] = _("plus or minus") + +# Translators: this is the spoken word for the character '²' (U+00b2) +# +chnames['\u00b2'] = _("superscript 2") + +# Translators: this is the spoken word for the character '³' (U+00b3) +# +chnames['\u00b3'] = _("superscript 3") + +# Translators: this is the spoken word for the character '´' (U+00b4) +# +chnames['\u00b4'] = _("acute") + +# Translators: this is the spoken word for the character 'µ' (U+00b5) +# +chnames['\u00b5'] = _("mu") + +# Translators: this is the spoken word for the character '¶' (U+00b6) +# +chnames['\u00b6'] = _("paragraph marker") + +# Translators: this is the spoken word for the character '·' (U+00b7) +# +chnames['\u00b7'] = _("middle dot") + +# Translators: this is the spoken word for the character '¸' (U+00b8) +# +chnames['\u00b8'] = _("cedilla") + +# Translators: this is the spoken word for the character '¹' (U+00b9) +# +chnames['\u00b9'] = _("superscript 1") + +# Translators: this is the spoken word for the character 'º' (U+00ba) +# +chnames['\u00ba'] = _("ordinal") + +# Translators: this is the spoken word for the character '»' (U+00bb) +# +chnames['\u00bb'] = _("right double angle bracket") + +# Translators: this is the spoken word for the character '¼' (U+00bc) +# +chnames['\u00bc'] = _("one fourth") + +# Translators: this is the spoken word for the character '½' (U+00bd) +# +chnames['\u00bd'] = _("one half") + +# Translators: this is the spoken word for the character '¾' (U+00be) +# +chnames['\u00be'] = _("three fourths") + +# Translators: this is the spoken word for the character '¿' (U+00bf) +# +chnames['\u00bf'] = _("inverted question mark") + +# Translators: this is the spoken word for the character 'á' (U+00e1) +# +chnames['\u00e1'] = _("a acute") + +# Translators: this is the spoken word for the character 'À' (U+00c0) +# +chnames['\u00c0'] = _("A GRAVE") + +# Translators: this is the spoken word for the character 'Á' (U+00c1) +# +chnames['\u00c1'] = _("A ACUTE") + +# Translators: this is the spoken word for the character 'Â' (U+00c2) +# +chnames['\u00c2'] = _("A CIRCUMFLEX") + +# Translators: this is the spoken word for the character 'Ã' (U+00c3) +# +chnames['\u00c3'] = _("A TILDE") + +# Translators: this is the spoken word for the character 'Ä' (U+00c4) +# +chnames['\u00c4'] = _("A UMLAUT") + +# Translators: this is the spoken word for the character 'Å' (U+00c5) +# +chnames['\u00c5'] = _("A RING") + +# Translators: this is the spoken word for the character 'Æ' (U+00c6) +# +chnames['\u00c6'] = _("A E") + +# Translators: this is the spoken word for the character 'Ç' (U+00c7) +# +chnames['\u00c7'] = _("C CEDILLA") + +# Translators: this is the spoken word for the character 'È' (U+00c8) +# +chnames['\u00c8'] = _("E GRAVE") + +# Translators: this is the spoken word for the character 'É' (U+00c9) +# +chnames['\u00c9'] = _("E ACUTE") + +# Translators: this is the spoken word for the character 'Ê' (U+00ca) +# +chnames['\u00ca'] = _("E CIRCUMFLEX") + +# Translators: this is the spoken word for the character 'Ë' (U+00cb) +# +chnames['\u00cb'] = _("E UMLAUT") + +# Translators: this is the spoken word for the character 'Ì' (U+00cc) +# +chnames['\u00cc'] = _("I GRAVE") + +# Translators: this is the spoken word for the character 'Í' (U+00cd) +# +chnames['\u00cd'] = _("I ACUTE") + +# Translators: this is the spoken word for the character 'Î' (U+00ce) +# +chnames['\u00ce'] = _("I CIRCUMFLEX") + +# Translators: this is the spoken word for the character 'Ï' (U+00cf) +# +chnames['\u00cf'] = _("I UMLAUT") + +# Translators: this is the spoken word for the character 'Ð' (U+00d0) +# +chnames['\u00d0'] = _("ETH") + +# Translators: this is the spoken word for the character 'Ñ' (U+00d1) +# +chnames['\u00d1'] = _("N TILDE") + +# Translators: this is the spoken word for the character 'Ò' (U+00d2) +# +chnames['\u00d2'] = _("O GRAVE") + +# Translators: this is the spoken word for the character 'Ó' (U+00d3) +# +chnames['\u00d3'] = _("O ACUTE") + +# Translators: this is the spoken word for the character 'Ô' (U+00d4) +# +chnames['\u00d4'] = _("O CIRCUMFLEX") + +# Translators: this is the spoken word for the character 'Õ' (U+00d5) +# +chnames['\u00d5'] = _("O TILDE") + +# Translators: this is the spoken word for the character 'Ö' (U+00d6) +# +chnames['\u00d6'] = _("O UMLAUT") + +# Translators: this is the spoken word for the character '×' (U+00d7) +# +chnames['\u00d7'] = _("times") + +# Translators: this is the spoken word for the character 'Ø' (U+00d8) +# +chnames['\u00d8'] = _("O STROKE") + +# Translators: this is the spoken word for the character 'Ù' (U+00d9) +# +chnames['\u00d9'] = _("U GRAVE") + +# Translators: this is the spoken word for the character 'Ú' (U+00da) +# +chnames['\u00da'] = _("U ACUTE") + +# Translators: this is the spoken word for the character 'Û' (U+00db) +# +chnames['\u00db'] = _("U CIRCUMFLEX") + +# Translators: this is the spoken word for the character 'Ü' (U+00dc) +# +chnames['\u00dc'] = _("U UMLAUT") + +# Translators: this is the spoken word for the character 'Ý' (U+00dd) +# +chnames['\u00dd'] = _("Y ACUTE") + +# Translators: this is the spoken word for the character 'Þ' (U+00de) +# +chnames['\u00de'] = _("THORN") + +# Translators: this is the spoken word for the character 'ß' (U+00df) +# +chnames['\u00df'] = _("s sharp") + +# Translators: this is the spoken word for the character 'à' (U+00e0) +# +chnames['\u00e0'] = _("a grave") + +# Translators: this is the spoken word for the character 'â' (U+00e2) +# +chnames['\u00e2'] = _("a circumflex") + +# Translators: this is the spoken word for the character 'ã' (U+00e3) +# +chnames['\u00e3'] = _("a tilde") + +# Translators: this is the spoken word for the character 'ä' (U+00e4) +# +chnames['\u00e4'] = _("a umlaut") + +# Translators: this is the spoken word for the character 'å' (U+00e5) +# +chnames['\u00e5'] = _("a ring") + +# Translators: this is the spoken word for the character 'æ' (U+00e6) +# +chnames['\u00e6'] = _("a e") + +# Translators: this is the spoken word for the character 'ç' (U+00e7) +# +chnames['\u00e7'] = _("c cedilla") + +# Translators: this is the spoken word for the character 'è' (U+00e8) +# +chnames['\u00e8'] = _("e grave") + +# Translators: this is the spoken word for the character 'é' (U+00e9) +# +chnames['\u00e9'] = _("e acute") + +# Translators: this is the spoken word for the character 'ê' (U+00ea) +# +chnames['\u00ea'] = _("e circumflex") + +# Translators: this is the spoken word for the character 'ë' (U+00eb) +# +chnames['\u00eb'] = _("e umlaut") + +# Translators: this is the spoken word for the character 'ì' (U+00ec) +# +chnames['\u00ec'] = _("i grave") + +# Translators: this is the spoken word for the character 'í' (U+00ed) +# +chnames['\u00ed'] = _("i acute") + +# Translators: this is the spoken word for the character 'î' (U+00ee) +# +chnames['\u00ee'] = _("i circumflex") + +# Translators: this is the spoken word for the character 'ï' (U+00ef) +# +chnames['\u00ef'] = _("i umlaut") + +# Translators: this is the spoken word for the character 'ð' (U+00f0) +# +chnames['\u00f0'] = _("eth") + +# Translators: this is the spoken word for the character 'ñ' (U+00f1) +# +chnames['\u00f1'] = _("n tilde") + +# Translators: this is the spoken word for the character 'ò' (U+00f2) +# +chnames['\u00f2'] = _("o grave") + +# Translators: this is the spoken word for the character 'ó' (U+00f3) +# +chnames['\u00f3'] = _("o acute") + +# Translators: this is the spoken word for the character 'ô' (U+00f4) +# +chnames['\u00f4'] = _("o circumflex") + +# Translators: this is the spoken word for the character 'õ' (U+00f5) +# +chnames['\u00f5'] = _("o tilde") + +# Translators: this is the spoken word for the character 'ö' (U+00f6) +# +chnames['\u00f6'] = _("o umlaut") + +# Translators: this is the spoken word for the character '÷' (U+00f7) +# +chnames['\u00f7'] = _("divided by") + +# Translators: this is the spoken word for the character 'ø' (U+00f8) +# +chnames['\u00f8'] = _("o stroke") + +# Translators: this is the spoken word for the character 'þ' (U+00fe) +# +chnames['\u00fe'] = _("thorn") + +# Translators: this is the spoken word for the character 'ú' (U+00fa) +# +chnames['\u00fa'] = _("u acute") + +# Translators: this is the spoken word for the character 'ù' (U+00f9) +# +chnames['\u00f9'] = _("u grave") + +# Translators: this is the spoken word for the character 'û' (U+00fb) +# +chnames['\u00fb'] = _("u circumflex") + +# Translators: this is the spoken word for the character 'ü' (U+00fc) +# +chnames['\u00fc'] = _("u umlaut") + +# Translators: this is the spoken word for the character 'ý' (U+00fd) +# +chnames['\u00fd'] = _("y acute") + +# Translators: this is the spoken word for the character 'ÿ' (U+00ff) +# +chnames['\u00ff'] = _("y umlaut") + +# Translators: this is the spoken word for the character 'Ÿ' (U+0178) +# +chnames['\u0178'] = _("Y UMLAUT") + +# Translators: this is the spoken word for the character 'ƒ' (U+0192) +# +chnames['\u0192'] = _("florin") + +# Translators: this is the spoken word for the character '–' (U+2013) +# +chnames['\u2013'] = _("en dash") + +# Translators: this is the spoken word for the left single quote: ‘ +# (U+2018) +# +chnames['\u2018'] = _("left single quote") + +# Translators: this is the spoken word for the right single quote: ’ +# (U+2019) +# +chnames['\u2019'] = _("right single quote") + +# Translators: this is the spoken word for the character '‚' (U+201a) +# +chnames['\u201a'] = _("single low quote") + +# Translators: this is the spoken word for the character '“' (U+201c) +# +chnames['\u201c'] = _("left double quote") + +# Translators: this is the spoken word for the character '”' (U+201d) +# +chnames['\u201d'] = _("right double quote") + +# Translators: this is the spoken word for the character '„' (U+201e) +# +chnames['\u201e'] = _("double low quote") + +# Translators: this is the spoken word for the character '†' (U+2020) +# +chnames['\u2020'] = _("dagger") + +# Translators: this is the spoken word for the character '‡' (U+2021) +# +chnames['\u2021'] = _("double dagger") + +# Translators: this is the spoken word for the character '•' (U+2022) +# +chnames['\u2022'] = _("bullet") + +# Translators: this is the spoken word for the character '‣' (U+2023) +# +chnames['\u2023'] = _("triangular bullet") + +# Translators: this is the spoken word for the character '‰' (U+2030) +# +chnames['\u2030'] = _("per mille") + +# Translators: this is the spoken word for the character '′' (U+2032) +# +chnames['\u2032'] = _("prime") + +# Translators: this is the spoken word for the character '″' (U+2033) +# +chnames['\u2033'] = _("double prime") + +# Translators: this is the spoken word for the character '‴' (U+2034) +# +chnames['\u2034'] = _("triple prime") + +# Translators: this is the spoken word for the character '⁃' (U+2043) +# +chnames['\u2043'] = _("hyphen bullet") + +# Translators: this is the spoken word for the character '€' (U+20ac) +# +chnames['\u20ac'] = _("euro") + +# Translators: this is the spoken word for the character '™' (U+2122) +# +chnames['\u2122'] = _("trademark") + +# Translators: this is the spoken word for the character '✓' (U+2713) +# It can be used as a bullet in a list. +# +chnames['\u2713'] = _("check mark") + +# Translators: this is the spoken word for the character '✔' (U+2714) +# It can be used as a bullet in a list. +# +chnames['\u2714'] = _("heavy check mark") + +# Translators: this is the spoken word for the character 'x' (U+2717) +# This symbol is included here because it can be used as a bullet in +# an OOo list. The goal is to inform the user of the appearance of +# the bullet, while making it clear that it is a bullet and not simply +# the typed letter 'x'. "Ballot x" might confuse the user. Hence the +# use of "x-shaped bullet". +# +chnames['\u2717'] = _("x-shaped bullet") + +# Translators: this is the spoken word for the character '⁰' (U+2070) +# +chnames['\u2070'] = _("superscript 0") + +# Translators: this is the spoken word for the character '⁴' (U+2074) +# +chnames['\u2074'] = _("superscript 4") + +# Translators: this is the spoken word for the character '⁵' (U+2075) +# +chnames['\u2075'] = _("superscript 5") + +# Translators: this is the spoken word for the character '⁶' (U+2076) +# +chnames['\u2076'] = _("superscript 6") + +# Translators: this is the spoken word for the character '⁷' (U+2077) +# +chnames['\u2077'] = _("superscript 7") + +# Translators: this is the spoken word for the character '⁸' (U+2078) +# +chnames['\u2078'] = _("superscript 8") + +# Translators: this is the spoken word for the character '⁹' (U+2079) +# +chnames['\u2079'] = _("superscript 9") + +# Translators: this is the spoken word for the character '⁺' (U+207a) +# +chnames['\u207a'] = _("superscript plus") + +# Translators: this is the spoken word for the character '⁻' (U+207b) +# +chnames['\u207b'] = _("superscript minus") + +# Translators: this is the spoken word for the character '⁼' (U+207c) +# +chnames['\u207c'] = _("superscript equals") + +# Translators: this is the spoken word for the character '⁽' (U+207d) +# +chnames['\u207d'] = _("superscript left paren") + +# Translators: this is the spoken word for the character '⁾' (U+207e) +# +chnames['\u207e'] = _("superscript right paren") + +# Translators: this is the spoken word for the character 'ⁿ' (U+207f) +# +chnames['\u207f'] = _("superscript n") + +# Translators: this is the spoken word for the character '₀' (U+2080) +# +chnames['\u2080'] = _("subscript 0") + +# Translators: this is the spoken word for the character '₁' (U+2081) +# +chnames['\u2081'] = _("subscript 1") + +# Translators: this is the spoken word for the character '₂' (U+2082) +# +chnames['\u2082'] = _("subscript 2") + +# Translators: this is the spoken word for the character '₃' (U+2083) +# +chnames['\u2083'] = _("subscript 3") + +# Translators: this is the spoken word for the character '₄' (U+2084) +# +chnames['\u2084'] = _("subscript 4") + +# Translators: this is the spoken word for the character '₅' (U+2085) +# +chnames['\u2085'] = _("subscript 5") + +# Translators: this is the spoken word for the character '₆' (U+2086) +# +chnames['\u2086'] = _("subscript 6") + +# Translators: this is the spoken word for the character '₇' (U+2087) +# +chnames['\u2087'] = _("subscript 7") + +# Translators: this is the spoken word for the character '₈' (U+2088) +# +chnames['\u2088'] = _("subscript 8") + +# Translators: this is the spoken word for the character '₉' (U+2089) +# +chnames['\u2089'] = _("subscript 9") + +# Translators: this is the spoken word for the character '₊' (U+208a) +# +chnames['\u208a'] = _("subscript plus") + +# Translators: this is the spoken word for the character '₋' (U+208b) +# +chnames['\u208b'] = _("subscript minus") + +# Translators: this is the spoken word for the character '₌' (U+208c) +# +chnames['\u208c'] = _("subscript equals") + +# Translators: this is the spoken word for the character '₍' (U+208d) +# +chnames['\u208d'] = _("subscript left paren") + +# Translators: this is the spoken word for the character '₎' (U+208e) +# +chnames['\u208e'] = _("subscript right paren") + +# Translators: StarOffice/OOo includes private-use unicode character U+E00A +# as a bullet which looks like the black square: ■ (U+25A0). Therefore, +# please use the same translation for this character. +# +chnames['\ue00a'] = _("black square") + +# Translators: StarOffice/OOo includes private-use unicode character U+E00C +# as a bullet which looks like the black diamond: ◆ (U+25C6). Therefore, +# please use the same translation for this character. +# +chnames['\ue00c'] = _("black diamond") + +# Translators: This refers to U+FFFC, the "object replacement character." +# This character appears in the accessible text of documents and serves as +# indication of the presence of an object within the text (e.g. an image +# or form field inside a paragraph). In an application which has full +# accessibility support for embedded objects, Cthulhu should present the object +# and NOT speak this character. However, for applications where this support +# is missing, the user can arrow to this character and Cthulhu should not be +# silent. This string is what Cthulhu will speak to the user should this occur. +# More information about this character can be found at: +# * http://www.fileformat.info/info/unicode/char/fffc/index.htm +# * http://en.wikipedia.org/wiki/Specials_(Unicode_block) +# +chnames['\ufffc'] = _("object replacement character") + +def getCharacterName(character, preferMath=False): + """Given a character, return its name as people might refer to it + in ordinary conversation. + + Arguments: + - character: the character to get the name for + + Returns a string representing the name for the character + """ + + if not preferMath and cthulhu_state.activeScript: + preferMath = cthulhu_state.activeScript.utilities.isInMath() + if not preferMath: + return character + return mathsymbols.getCharacterName(character) or character diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cmdnames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cmdnames.py new file mode 100644 index 0000000..34ee347 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cmdnames.py @@ -0,0 +1,1162 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Command names which Cthulhu presents in speech and/or braille. These +have been put in their own module so that we can present them in +the correct language when users change the synthesizer language +on the fly without having to reload a bunch of modules.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team" +__license__ = "LGPL" + +from .cthulhu_i18n import _ + +# Translators: this command will move the mouse pointer to the current item +# without clicking on it. +ROUTE_POINTER_TO_ITEM = _("Route the pointer to the current item") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Left click means to generate a left mouse button click on the current item. +LEFT_CLICK_REVIEW_ITEM = _("Perform left click on current flat review item") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Right click means to generate a right mouse button click on the current item. +RIGHT_CLICK_REVIEW_ITEM = _("Perform right click on current flat review item") + +# Translators: the Cthulhu "SayAll" command allows the user to press a key and have +# the entire document in a window be automatically spoken to the user. If the +# user presses any key during a SayAll operation, the speech will be interrupted +# and the cursor will be positioned at the point where the speech was interrupted. +SAY_ALL = _("Speak entire document") + +# Translators: the 'flat review' feature of Cthulhu allows the user to explore the +# text in a window in a 2D fashion. That is, Cthulhu treats all the text from all +# objects in a window (e.g., buttons, labels, etc.) as a sequence of words in a +# sequence of lines. The flat review feature allows the user to explore this text +# by the {previous,next} {line,word,character}. This string is the name of a command +# which causes Cthulhu to speak the entire contents of the window using flat review. +SAY_ALL_FLAT_REVIEW = _("Speak entire window using flat review") + +# Translators: the "Where Am I" feature of Cthulhu allows a user to press a key and +# then have information about their current context spoken and brailled to them. +# For example, the information may include the name of the current pushbutton +# with focus as well as its mnemonic. +WHERE_AM_I_BASIC = _("Perform the basic Where Am I operation") + +# Translators: the "Where Am I" feature of Cthulhu allows a user to press a key and +# then have information about their current context spoken and brailled to them. +# For example, the information may include the name of the current pushbutton +# with focus as well as its mnemonic. +WHERE_AM_I_DETAILED = _("Perform the detailed Where Am I operation") + +# Translators: This is the description of a dedicated command to speak the +# current selection / highlighted object(s). For instance, in a text object, +# "selection" refers to the selected/highlighted text. In a spreadsheet, it +# refers to the selected/highlighted cells. In an file manager, it refers to +# the selected/highlighted icons. Etc. +WHERE_AM_I_SELECTION = _("Speak the current selection") + +# Translators: This is the description of a dedicated command to speak details +# about a link, such as the uri and type of link. +WHERE_AM_I_LINK = _("Speak link details") + +# Translators: This command will cause the dialog's default button name to be +# spoken and displayed in braille. The "default" button in a dialog box is the +# button that gets activated when Enter is pressed anywhere within that dialog +# box. +PRESENT_DEFAULT_BUTTON = _("Present the default button") + +# Translators: This command will cause the window's status bar contents to be +# spoken and displayed in braille. +PRESENT_STATUS_BAR = _("Present the status bar") + +# Translators: This command will cause the window's title to be spoken and +# displayed in braille. +PRESENT_TITLE = _("Present the title bar") + +# Translators: the Cthulhu "Find" dialog allows a user to search for text in a +# window and then move focus to that text. For example, they may want to find +# the "OK" button. +SHOW_FIND_GUI = _("Open the Find dialog") + +# Translators: Cthulhu has a command which presents a menu with accessible actions +# that can be performed on the current object. This is the name of that command. +SHOW_ACTIONS_LIST = _("Show actions list") + +# Translators: the Cthulhu "Find" dialog allows a user to search for text in a +# window and then move focus to that text. For example, they may want to find +# the "OK" button. This string is used for finding the next occurrence of a +# string. +FIND_NEXT = _("Search for the next instance of a string") + +# Translators: the Cthulhu "Find" dialog allows a user to search for text in a +# window and then move focus to that text. For example, they may want to find +# the "OK" button. This string is used for finding the previous occurrence of a +# string. +FIND_PREVIOUS = _("Search for the previous instance of a string") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +TOGGLE_FLAT_REVIEW = _("Enter and exit flat review mode") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This switch allows the user to restrict the flat review function to a specific object. +TOGGLE_RESTRICT_FLAT_REVIEW = _("Toggle restricting flat review to the current object") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# The home position is the beginning of the content in the window. +REVIEW_HOME = _("Move flat review to the home position") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# The home position is the last bit of information in the window. +REVIEW_END = _("Move flat review to the end position") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +REVIEW_PREVIOUS_LINE = \ + _("Move flat review to the beginning of the previous line") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +REVIEW_CURRENT_LINE = _("Speak the current flat review line") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This particular command will cause Cthulhu to spell the current line character +# by character. +REVIEW_SPELL_CURRENT_LINE = _("Spell the current flat review line") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This particular command will cause Cthulhu to spell the current line character +# by character phonetically, saying "Alpha" for "a", "Bravo" for "b" and so on. +REVIEW_PHONETIC_CURRENT_LINE = \ + _("Phonetically spell the current flat review line") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +REVIEW_NEXT_LINE = _("Move flat review to the beginning of the next line") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Previous will go backwards in the window until you reach the top (i.e., it +# will wrap across lines if necessary). +REVIEW_PREVIOUS_ITEM = _("Move flat review to the previous item or word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This command will speak the current word or item. +REVIEW_CURRENT_ITEM = _("Speak the current flat review item or word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This particular command will cause Cthulhu to spell the current word or item +# character by character. +REVIEW_SPELL_CURRENT_ITEM = _("Spell the current flat review item or word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This particular command will cause Cthulhu to spell the current word or item +# character by character phonetically, saying "Alpha" for "a", "Bravo" for "b" +# and so on. +REVIEW_PHONETIC_CURRENT_ITEM = \ + _("Phonetically spell the current flat review item or word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Next will go forwards in the window until you reach the end (i.e., it +# will wrap across lines if necessary). +REVIEW_NEXT_ITEM = _("Move flat review to the next item or word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Above in this case means geographically above, as if you drew a vertical +# line upward on the screen. +REVIEW_ABOVE = _("Move flat review to the word above the current word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# With respect to this command, the flat review object is typically something +# like a pushbutton, a label, or some other GUI widget. The 'speaks' means it +# will speak the text associated with the object. +REVIEW_CURRENT_ACCESSIBLE = _("Speak the current flat review object") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Below in this case means geographically below, as if you drew a vertical +# line downward on the screen. +REVIEW_BELOW = _("Move flat review to the word below the current word") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Previous will go backwards in the window until you reach the top (i.e., it +# will wrap across lines if necessary). +REVIEW_PREVIOUS_CHARACTER = _("Move flat review to the previous character") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This command will speak the current character +REVIEW_CURRENT_CHARACTER = _("Speak the current flat review character") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This particular command will cause Cthulhu to present the character phonetically, +# saying "Alpha" for "a", "Bravo" for "b" and so on. +REVIEW_SPELL_CURRENT_CHARACTER = \ + _("Phonetically speak the current flat review character") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This particular command will cause Cthulhu to present the character's unicode +# value. +REVIEW_UNICODE_CURRENT_CHARACTER = \ + _("Speak unicode value of the current flat review character") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Previous will go forwards in the window until you reach the end (i.e., it +# will wrap across lines if necessary). +REVIEW_NEXT_CHARACTER = _("Move flat review to the next character") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This command will move to and present the end of the line. +REVIEW_END_OF_LINE = _("Move flat review to the end of the line") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# The bottom left is the bottom left of the window currently being reviewed. +REVIEW_BOTTOM_LEFT = _("Move flat review to the bottom left") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This command lets the user copy the contents currently being reviewed to the +# clipboard. +FLAT_REVIEW_COPY = _("Copy the contents under flat review to the clipboard") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# This command lets the user append the contents currently being reviewed to +# the existing contents of the clipboard. +FLAT_REVIEW_APPEND = \ + _("Append the contents under flat review to the clipboard") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Normally the contents are navigated without leaving the application being +# reviewed. There is a command which will place the entire contents of the +# flat review representation into a text view to make it easy to review +# and copy the text. This string describes that command. +FLAT_REVIEW_SHOW_CONTENTS = _("Show flat review contents") + +# Translators: when users are navigating a table, they sometimes want the +# entire row of a table read; other times they just want the current cell +# to be presented to them. +TOGGLE_TABLE_CELL_READ_MODE = \ + _("Toggle whether to read just the current table cell or the whole row") + +# Translators: the attributes being presented are the text attributes, such as +# bold, italic, font name, font size, etc. +READ_CHAR_ATTRIBUTES = \ + _("Read the attributes associated with the current text character") + +# Translators: a refreshable braille display is an external hardware device that +# presents braille characters to the user. There are a limited number of cells +# on the display (typically 40 cells). Cthulhu provides the feature to build up a +# longer logical line and allow the user to press buttons on the braille display +# so they can pan left and right over this line. +PAN_BRAILLE_LEFT = _("Pan the braille display to the left") + +# Translators: a refreshable braille display is an external hardware device that +# presents braille characters to the user. There are a limited number of cells +# on the display (typically 40 cells). Cthulhu provides the feature to build up a +# longer logical line and allow the user to press buttons on the braille display +# so they can pan left and right over this line. +PAN_BRAILLE_RIGHT = _("Pan the braille display to the right") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Flat review is modal, and the user can be exploring the window without +# changing which object in the window which has focus. The feature used here +# will return the flat review to the object with focus. +GO_BRAILLE_HOME = _("Return to object with keyboard focus") + +# Translators: braille can be displayed in many ways. Contracted braille +# provides a more efficient means to represent text, especially long +# documents. The feature used here is an option to toggle between contracted +# and uncontracted. +SET_CONTRACTED_BRAILLE = _("Turn contracted braille on and off") + +# Translators: hardware braille displays often have buttons near each braille +# cell. These are called cursor routing keys and are a way for a user to tell +# the machine they are interested in a particular character on the display. +PROCESS_ROUTING_KEY = _("Process a cursor routing key") + +# Translators: this is used to indicate the start point of a text selection. +PROCESS_BRAILLE_CUT_BEGIN = _("Mark the beginning of a text selection") + +# Translators: this is used to indicate the end point of a text selection. +PROCESS_BRAILLE_CUT_LINE = _("Mark the end of a text selection") + +# Translators: Cthulhu has a "Learn Mode" that will allow the user to type any key +# on the keyboard and hear what the effects of that key would be. The effects +# might be what Cthulhu would do if it had a handler for the particular key +# combination, or they might just be to echo the name of the key if Cthulhu doesn't +# have a handler. +ENTER_LEARN_MODE = _("Enter learn mode. Press escape to exit learn mode") + +# Translators: the speech rate is how fast the speech synthesis engine will +# generate speech. +DECREASE_SPEECH_RATE = _("Decrease the speech rate") + +# Translators: the speech rate is how fast the speech synthesis engine will +# generate speech. +INCREASE_SPEECH_RATE = _("Increase the speech rate") + +# Translators: the speech pitch is how high or low in pitch/frequency the +# speech synthesis engine will generate speech. +DECREASE_SPEECH_PITCH = _("Decrease the speech pitch") + +# Translators: the speech pitch is how high or low in pitch/frequency the +# speech synthesis engine will generate speech. +INCREASE_SPEECH_PITCH = _("Increase the speech pitch") + +# Translators: the speech volume is how high or low in gain/volume the +# speech synthesis engine will generate speech. +INCREASE_SPEECH_VOLUME = _("Increase the speech volume") + +# Translators: the speech volume is how high or low in gain/volume the +# speech synthesis engine will generate speech. +DECREASE_SPEECH_VOLUME = _("Decrease the speech volume") + +# Translators: Cthulhu allows the user to turn speech synthesis on or off. +# We call it 'silencing'. +TOGGLE_SPEECH = _("Toggle the silencing of speech") + +# Translators: Cthulhu's verbosity levels control how much (or how little) +# Cthulhu will speak when presenting objects as the user navigates within +# applications and reads content. The levels can be toggled via command. +# This string describes that command. +TOGGLE_SPEECH_VERBOSITY = _("Toggle speech verbosity level") + +# Translators: this string is associated with the keyboard shortcut to toggle sleepmode +TOGGLE_SLEEP_MODE = _("Toggle sleep mode") + +# Translators: this string is associated with the keyboard shortcut to quit +# Cthulhu. +QUIT_CTHULHU = _("Quit the screen reader") + +# Translators: the preferences configuration dialog is the dialog that allows +# users to set their preferences for Cthulhu. +SHOW_PREFERENCES_GUI = _("Display the preferences configuration dialog") + +# Translators: the preferences configuration dialog is the dialog that allows +# users to set their preferences for a specific application within Cthulhu. +SHOW_APP_PREFERENCES_GUI = \ + _("Display the application preferences configuration dialog") + +# Translators: Cthulhu allows the user to enable/disable speaking of indentation +# and justification. +TOGGLE_SPOKEN_INDENTATION_AND_JUSTIFICATION = \ + _("Toggle the speaking of indentation and justification") + +# Translators: Cthulhu has a setting through which users can control how a number is +# spoken. The options are digits ("1 2 3") and words ("one hundred and twenty +# three"). This string to be translated refers to an Cthulhu command for quickly +# toggling between the two options. +CHANGE_NUMBER_STYLE = _("Change spoken number style") + +# Translators: Cthulhu allows users to cycle through punctuation levels. None, +# some, most, or all, punctuation will be spoken. +CYCLE_PUNCTUATION_LEVEL = _("Cycle to the next speaking of punctuation level") + +# Translators: Cthulhu allows users to cycle through the speech synthesizers +# available on their system, such as espeak, voxin, mbrola, etc. This string +# is the description of the command. +CYCLE_SYNTHESIZER = _("Cycle to the next speech synthesizer") + +# Translators: Cthulhu has a feature whereby users can set up different "profiles," +# which are collection of settings which apply to a given task, such as a +# "Spanish" profile which would use Spanish text-to-speech and Spanish braille +# and selected when reading Spanish content. This string to be translated refers +# to an Cthulhu command which makes it possible for users to quickly cycle amongst +# their saved profiles without having to get into a GUI. +CYCLE_SETTINGS_PROFILE = _("Cycle to the next settings profile") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via text- +# to-speech. Speech Dispatcher has a feature to control how capital letters are +# presented: Do nothing at all, say the word 'capital' prior to presenting a +# capital letter, or play a tone which Speech Dispatcher refers to as a sound +# 'icon'. This string to be translated refers to an Cthulhu command which makes it +# possible for users to quickly cycle amongst these alternatives without having +# to get into a GUI. +CYCLE_CAPITALIZATION_STYLE = _("Cycle to the next capitalization style") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; "world" spoken when +# the period is pressed. +# - sentence echo: "Hello world" spoken when the period is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo. The following string refers to a command that allows the user to quickly +# choose which type of echo is being used. +CYCLE_KEY_ECHO = _("Cycle to the next key echo level") + +# Translators: this is a debug message that Cthulhu users will not normally see. It +# describes a debug routine that allows the user to adjust the level of debug +# information that Cthulhu generates at run time. +CYCLE_DEBUG_LEVEL = _("Cycle the debug level at run time") + +# Translators: this command announces information regarding the relationship of +# the given bookmark to the current position. Note that in this context, the +# "bookmark" is storing the location of an accessible object, typically on a web +# page. +BOOKMARK_CURRENT_WHERE_AM_I = \ + _("Bookmark where am I with respect to current position") + +# Translators: this event handler cycles through the registered bookmarks and +# takes the user to the previous bookmark location. Note that in this context, +# the "bookmark" is storing the location of an accessible object, typically on +# a web page. +BOOKMARK_GO_TO_PREVIOUS = _("Go to previous bookmark location") + +# Translators: this command moves the user to the location stored at the bookmark. +# Note that in this context, the "bookmark" is storing the location of an +# accessible object, typically on a web page. +BOOKMARK_GO_TO = _("Go to bookmark") + +# Translators: this event handler cycles through the registered bookmarks and +# takes the user to the next bookmark location. Note that in this context, the +# "bookmark" is storing the location of an accessible object, typically on a web +# page. +BOOKMARK_GO_TO_NEXT = _("Go to next bookmark location") + +# Translators: this event handler binds an in-page accessible object location to +# the given input key command. +BOOKMARK_ADD = _("Add bookmark") + +# Translators: this event handler saves all bookmarks for the current application +# to disk. +BOOKMARK_SAVE = _("Save bookmarks") + +# Translators: Cthulhu allows the item under the pointer to be spoken. This toggles +# the feature without the need to get into a GUI. +MOUSE_REVIEW_TOGGLE = _("Toggle mouse review mode") + +# Translators: Cthulhu has a command to present the current time in speech and in +# braille. +PRESENT_CURRENT_TIME = _("Present current time") + +# Translators: Cthulhu has a command to present the current date in speech and in +# braille. +PRESENT_CURRENT_DATE = _("Present current date") + +# Translators: Cthulhu has a command to present the pixel size and location of +# the current object. This string is how this command is described in the list +# of keyboard shortcuts. +PRESENT_SIZE_AND_POSITION = _("Present size and location of current object") + +# Translators: Cthulhu normally intercepts all keyboard commands and only passes +# them along to the current application when they are not Cthulhu commands. This +# command causes the next command issued to be passed along to the current +# application, bypassing Cthulhu's interception of it. +BYPASS_NEXT_COMMAND = \ + _("Pass the next command on to the current application") + +# Translators: Cthulhu has a command to review previous chat room messages in +# speech and braille. This string to be translated is associated with the +# keyboard commands used to review those previous messages. +CHAT_PREVIOUS_MESSAGE = _("Speak and braille a previous chat room message") + +# Translators: In chat applications, it is often possible to see that a "buddy" +# is typing currently (e.g. via a keyboard icon or status text). Some users like +# to have this typing status announced by Cthulhu; others find that announcement +# unpleasant. Therefore, it is a setting in Cthulhu. This string to be translated +# is associated with the command to toggle typing status presentation on or off. +CHAT_TOGGLE_BUDDY_TYPING = \ + _("Toggle whether we announce when our buddies are typing") + +# Translators: Cthulhu has a command to review previous chat room messages in +# speech and braille. Some users prefer to have this message history combined +# (e.g. the last ten messages which came in, no matter what room they came +# from). Other users prefer to have specific room history (e.g. the last ten +# messages from #a11y). Therefore, this is a setting in Cthulhu. This string to be +# translated is associated with the command to toggle specific room history on +# or off. +CHAT_TOGGLE_MESSAGE_HISTORIES = \ + _("Toggle whether we provide chat room specific message " \ + "histories") + +# Translators: In chat applications, Cthulhu automatically presents incoming +# messages in speech and braille. If a user is in multiple conversations or +# channels at the same time, it can be confusing to know what room or channel +# a given message came from just from hearing/reading it. For this reason, Cthulhu +# has an option to present the name of the room first ("#a11y hello!" +# instead of " hello!"). This string to be translated is associated with +# the command to toggle room name presentation on or off. +CHAT_TOGGLE_ROOM_NAME_PREFIX = \ + _("Toggle whether we prefix chat room messages with " \ + "the name of the chat room") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls to the left. +BRAILLE_LINE_LEFT = _("Line Left") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls to the right. +BRAILLE_LINE_RIGHT = _("Line Right") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls up. +BRAILLE_LINE_UP = _("Line Up") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls down. +BRAILLE_LINE_DOWN = _("Line Down") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, it instructs the braille display to freeze. +BRAILLE_FREEZE = _("Freeze") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls to the top left of the window. +BRAILLE_TOP_LEFT = _("Top Left") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls to the bottom left of the window. +BRAILLE_BOTTOM_LEFT = _("Bottom Left") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display scrolls to position containing the cursor. +BRAILLE_HOME = _("Cursor Position") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). When pressing the +# button, the display toggles between six-dot braille and eight-dot braille. +BRAILLE_SIX_DOTS = _("Six Dots") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). This command +# represents a whole set of buttons known as cursor routing keys and are a way +# for a user to move the application's caret to the position indicated on the +# display. +BRAILLE_ROUTE_CURSOR = _("Cursor Routing") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). This command +# represents the start of a selection operation. It is called "Cut Begin" to map +# to what BrlTTY users are used to: in character cell mode operation on virtual +# consoles, the act of copying text is erroneously called a "cut" operation. +BRAILLE_CUT_BEGIN = _("Cut Begin") + +# Translators: this is a command for a button on a refreshable braille display +# (an external hardware device used by people who are blind). This command +# represents marking the endpoint of a selection. It is called "Cut Line" to map +# to what BrlTTY users are used to: in character cell mode operation on virtual +# consoles, the act of copying text is erroneously called a "cut" operation. +BRAILLE_CUT_LINE = _("Cut Line") + +# Translators: this is a command which causes Cthulhu to present the last received +# notification message. +NOTIFICATION_MESSAGES_LAST = _("Present last notification message") + +# Translators: this is a command which causes Cthulhu to present a list of all the +# notification messages received. +NOTIFICATION_MESSAGES_LIST = _("Present notification messages list") + +# Translators: this is a command which causes Cthulhu to present the previous +# notification message. +NOTIFICATION_MESSAGES_PREVIOUS = _("Present previous notification message") + +# Translators: this is a command which causes Cthulhu to present the next +# notification message. +NOTIFICATION_MESSAGES_NEXT = _("Present next notification message") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_NEXT_CHAR = _("Go to next character") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_PREV_CHAR = _("Go to previous character") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_NEXT_WORD = _("Go to next word") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_PREV_WORD = _("Go to previous word") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_NEXT_LINE = _("Go to next line") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_PREV_LINE = _("Go to previous line") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_FILE_START = _("Go to the top of the file") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_FILE_END = _("Go to the bottom of the file") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_LINE_START = _("Go to the beginning of the line") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_LINE_END = _("Go to the end of the line") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_NEXT_OBJECT = _("Go to the next object") + +# Translators: this is a command related to navigating within a document. +CARET_NAVIGATION_PREV_OBJECT = _("Go to the previous object") + +# Translators: this is for causing a collapsed combo box which was reached +# by Cthulhu's caret navigation to be expanded. +CARET_NAVIGATION_EXPAND_COMBO_BOX = \ + _("Cause the current combo box to be expanded") + +# Translators: Gecko native caret navigation is where Firefox (or Thunderbird) +# itself controls how the arrow keys move the caret around HTML content. It's +# often broken, so Cthulhu needs to provide its own support. As such, Cthulhu offers +# the user the ability to toggle which application is controlling the caret. +CARET_NAVIGATION_TOGGLE = \ + _("Switch between native and screen-reader caret navigation") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This string refers to a command +# to cycle through the different "politeness" levels. +LIVE_REGIONS_ADVANCE_POLITENESS = _("Advance live region politeness setting") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This string refers to a command +# to turn off live regions by default. +LIVE_REGIONS_SET_POLITENESS_OFF = \ + _("Set default live region politeness level to off") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# This string refers to a command for reviewing up to nine stored previous live +# messages. +LIVE_REGIONS_REVIEW = _("Review live region announcement") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# This string refers to an Cthulhu command which allows the user to toggle whether +# or not Cthulhu pays attention to changes in live regions. Note that turning off +# monitoring of live events is NOT the same as turning the politeness level +# to "off". The user can opt to have no notifications presented (politeness +# level of "off") and still manually review recent updates to live regions via +# Cthulhu commands for doing so -- as long as the monitoring of live regions is +# enabled. +LIVE_REGIONS_MONITOR = _("Monitor live regions") + +# Translators: hovering the mouse over certain objects on a web page causes a +# new object to appear such as a pop-up menu. This command will move the user +# to the object which just appeared as a result of the user hovering the mouse. +# If the user is already in the mouse over object, this command will hide the +# mouse over and return the user to the object he/she was in. +MOUSE_OVER_MOVE = _("Move focus into and away from the current mouse over") + +# Translators: Cthulhu allows you to dynamically define which row of a spreadsheet +# or table should be treated as containing column headers. This string refers to +# the command to set the row. +DYNAMIC_COLUMN_HEADER_SET = _("Set the row to use as dynamic column headers") + +# Translators: Cthulhu allows you to dynamically define which row of a spreadsheet +# or table should be treated as containing column headers. This string refers to +# the command to unset the row so it is no longer treated as if it contained +# column headers. +DYNAMIC_COLUMN_HEADER_CLEAR = _("Clear the dynamic column headers") + +# Translators: Cthulhu allows you to dynamically define which column of a +# spreadsheet or table should be treated as containing row headers. This +# string refers to the command to set the column. +DYNAMIC_ROW_HEADER_SET = _("Set the column to use as dynamic row headers") + +# Translators: Cthulhu allows you to dynamically define which column of a +# spreadsheet or table should be treated as containing column headers. This +# string refers to the command to unset the column so it is no longer treated +# as if it contained row headers. +DYNAMIC_ROW_HEADER_CLEAR = _("Clear the dynamic row headers") + +# Translators: This string refers to an Cthulhu command. The "input line" refers +# to the place where one enters formulas for a spreadsheet. +PRESENT_INPUT_LINE = _("Present the contents of the input line") + +# Translators: the structural navigation keys are designed to move the caret +# around the document content by object type. Thus H moves you to the next +# heading, Shift H to the previous heading, T to the next table, and so on. +# This feature needs to be toggle-able so that it does not interfere with normal +# writing functions. +STRUCTURAL_NAVIGATION_TOGGLE = _("Toggle structural navigation keys") + +# Translators: this is for navigating among blockquotes in a document. +BLOCKQUOTE_PREV = _("Go to previous blockquote") + +# Translators: this is for navigating among blockquotes in a document. +BLOCKQUOTE_NEXT = _("Go to next blockquote") + +# Translators: this is for navigating among blockquotes in a document. +BLOCKQUOTE_LIST = _("Display a list of blockquotes") + +# Translators: this is for navigating among buttons in a document. +BUTTON_PREV = _("Go to previous button") + +# Translators: this is for navigating among buttons in a document. +BUTTON_NEXT = _("Go to next button") + +# Translators: this is for navigating among buttons in a document. +BUTTON_LIST = _("Display a list of buttons") + +# Translators: this is for navigating among check boxes in a document. +CHECK_BOX_PREV = _("Go to previous check box") + +# Translators: this is for navigating among check boxes in a document. +CHECK_BOX_NEXT = _("Go to next check box") + +# Translators: this is for navigating among check boxes in a document. +CHECK_BOX_LIST = _("Display a list of check boxes") + +# Translators: this is for navigating among clickable objects in a document. +# A "clickable" is a web element with an "onClick" handler. +CLICKABLE_PREV = _("Go to previous clickable") + +# Translators: this is for navigating among clickable objects in a document. +# A "clickable" is a web element with an "onClick" handler. +CLICKABLE_NEXT = _("Go to next clickable") + +# Translators: this is for navigating among clickable objects in a document. +# A "clickable" is a web element with an "onClick" handler. +CLICKABLE_LIST = _("Display a list of clickables") + +# Translators: this is for navigating among combo boxes in a document. +COMBO_BOX_PREV = _("Go to previous combo box") + +# Translators: this is for navigating among combo boxes in a document. +COMBO_BOX_NEXT = _("Go to next combo box") + +# Translators: This string describes a document navigation command which moves +# to the start of the current container. Examples of containers include tables, +# lists, and blockquotes. +CONTAINER_START = _("Go to start of container") + +# Translators: This string describes a document navigation command which moves +# to the end of the current container. Examples of containers include tables, +# lists, and blockquotes. +CONTAINER_END = _("Go to end of container") + +# Translators: this is for navigating among combo boxes in a document. +COMBO_BOX_LIST = _("Display a list of combo boxes") + +# Translators: this is for navigating among entries in a document. +ENTRY_PREV = _("Go to previous entry") + +# Translators: this is for navigating among entries in a document. +ENTRY_NEXT = _("Go to next entry") + +# Translators: this is for navigating among entries in a document. +ENTRY_LIST = _("Display a list of entries") + +# Translators: this is for navigating among form fields in a document. +FORM_FIELD_PREV = _("Go to previous form field") + +# Translators: this is for navigating among form fields in a document. +FORM_FIELD_NEXT = _("Go to next form field") + +# Translators: this is for navigating among form fields in a document. +FORM_FIELD_LIST = _("Display a list of form fields") + +# Translators: this is for navigating among headings (e.g.

) in a document. +HEADING_PREV = _("Go to previous heading") + +# Translators: this is for navigating among headings (e.g.

) in a document. +HEADING_NEXT = _("Go to next heading") + +# Translators: this is for navigating among headings (e.g.

) in a document. +HEADING_LIST = _("Display a list of headings") + +# Translators: this is for navigating among headings (e.g.

) in a document. +#

is a heading at level 1,

is a heading at level 2, etc. +HEADING_AT_LEVEL_PREV = _("Go to previous heading at level %d") + +# Translators: this is for navigating among headings (e.g.

) in a document. +#

is a heading at level 1,

is a heading at level 2, etc. +HEADING_AT_LEVEL_NEXT = _("Go to next heading at level %d") + +# Translators: this is for navigating among headings (e.g.

) in a document. +#

is a heading at level 1,

is a heading at level 2, etc. +HEADING_AT_LEVEL_LIST = _("Display a list of headings at level %d") + +# Translators: this is for navigating among iframes in a document. +IFRAME_PREV = _("Go to previous internal frame") + +# Translators: this is for navigating among iframes in a document. +IFRAME_NEXT = _("Go to next internal frame") + +# Translators: this is for navigating among images in a document. +IFRAME_LIST = _("Display a list of internal frames") + +# Translators: this is for navigating among images in a document. +IMAGE_PREV = _("Go to previous image") + +# Translators: this is for navigating among images in a document. +IMAGE_NEXT = _("Go to next image") + +# Translators: this is for navigating among images in a document. +IMAGE_LIST = _("Display a list of images") + +# Translators: this is for navigating among ARIA landmarks in a document. ARIA +# role landmarks are the W3C defined HTML tag attribute 'role' used to identify +# important part of webpage like banners, main context, search etc. +LANDMARK_PREV = _("Go to previous landmark") + +# Translators: this is for navigating among ARIA landmarks in a document. ARIA +# role landmarks are the W3C defined HTML tag attribute 'role' used to identify +# important part of webpage like banners, main context, search etc. +LANDMARK_NEXT = _("Go to next landmark") + +# Translators: this is for navigating among ARIA landmarks in a document. ARIA +# role landmarks are the W3C defined HTML tag attribute 'role' used to identify +# important part of webpage like banners, main context, search etc. +LANDMARK_LIST = _("Display a list of landmarks") + +# Translators: this is for navigating among large objects in a document. +# A 'large object' is a logical chunk of text, such as a paragraph, a list, +# a table, etc. +LARGE_OBJECT_PREV = _("Go to previous large object") + +# Translators: this is for navigating among large objects in a document. +# A 'large object' is a logical chunk of text, such as a paragraph, a list, +# a table, etc. +LARGE_OBJECT_NEXT = _("Go to next large object") + +# Translators: this is for navigating among large objects in a document. +# A 'large object' is a logical chunk of text, such as a paragraph, a list, +# a table, etc. +LARGE_OBJECT_LIST = _("Display a list of large objects") + +# Translators: this is for navigating among links in a document. +LINK_PREV = _("Go to previous link") + +# Translators: this is for navigating among links in a document. +LINK_NEXT = _("Go to next link") + +# Translators: this is for navigating among links in a document. +LINK_LIST = _("Display a list of links") + +# Translators: this is for navigating among lists in a document. +LIST_PREV = _("Go to previous list") + +# Translators: this is for navigating among lists in a document. +LIST_NEXT = _("Go to next list") + +# Translators: this is for navigating among lists in a document. +LIST_LIST = _("Display a list of lists") + +# Translators: this is for navigating among list items in a document. +LIST_ITEM_PREV = _("Go to previous list item") + +# Translators: this is for navigating among list items in a document. +LIST_ITEM_NEXT = _("Go to next list item") + +# Translators: this is for navigating among list items in a document. +LIST_ITEM_LIST = _("Display a list of list items") + +# Translators: this is for navigating among live regions in a document. A live +# region is an area of a web page that is periodically updated, e.g. a stock +# ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +LIVE_REGION_PREV = _("Go to previous live region") + +# Translators: this is for navigating among live regions in a document. A live +# region is an area of a web page that is periodically updated, e.g. a stock +# ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +LIVE_REGION_NEXT = _("Go to next live region") + +# Translators: this is for navigating among live regions in a document. A live +# region is an area of a web page that is periodically updated, e.g. a stock +# ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +LIVE_REGION_LAST = _("Go to the last live region which made an announcement") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. +NAVIGATOR_UP = _("Go to the parent of the object with navigator focus.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. +NAVIGATOR_DOWN = _("Go to the first child of the object with navigator focus.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. +NAVIGATOR_NEXT = _("Go to the next sibling of the object with navigator focus.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. +NAVIGATOR_PREVIOUS = _("Go to the previous sibling of the object with navigator focus.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. Users are also able to synthesize a click on the objects. +NAVIGATOR_PERFORM_ACTION = _("Click on the object with navigator focus.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This hierarchy can be simplified, and the simplification can be +# toggled on and off. +NAVIGATOR_TOGGLE_SIMPLIFIED = _("Toggle simplified object navigation.") + +# Translators: this is for navigating among paragraphs in a document. +PARAGRAPH_PREV = _("Go to previous paragraph") + +# Translators: this is for navigating among paragraphs in a document. +PARAGRAPH_NEXT = _("Go to next paragraph") + +# Translators: this is for navigating among paragraphs in a document. +PARAGRAPH_LIST = _("Display a list of paragraphs") + +# Translators: this is for navigating among radio buttons in a document. +RADIO_BUTTON_PREV = _("Go to previous radio button") + +# Translators: this is for navigating among radio buttons in a document. +RADIO_BUTTON_NEXT = _("Go to next radio button") + +# Translators: this is for navigating among radio buttons in a document. +RADIO_BUTTON_LIST = _("Display a list of radio buttons") + +# Translators: this is for navigating among separators (e.g.
) in a +# document. +SEPARATOR_PREV = _("Go to previous separator") + +# Translators: this is for navigating among separators (e.g.
) in a +# document. +SEPARATOR_NEXT = _("Go to next separator") + +# Translators: this is for navigating among tables in a document. +TABLE_PREV = _("Go to previous table") + +# Translators: this is for navigating among tables in a document. +TABLE_NEXT = _("Go to next table") + +# Translators: this is for navigating among tables in a document. +TABLE_LIST = _("Display a list of tables") + +# Translators: this is for navigating among table cells in a document. +TABLE_CELL_DOWN = _("Go down one cell") + +# Translators: this is for navigating among table cells in a document. +TABLE_CELL_FIRST = _("Go to the first cell in a table") + +# Translators: this is for navigating among table cells in a document. +TABLE_CELL_LAST = _("Go to the last cell in a table") + +# Translators: this is for navigating among table cells in a document. +TABLE_CELL_LEFT = _("Go left one cell") + +# Translators: this is for navigating among table cells in a document. +TABLE_CELL_RIGHT = _("Go right one cell") + +# Translators: this is for navigating among table cells in a document. +TABLE_CELL_UP = _("Go up one cell") + +# Translators: When presenting the content of a line on a web page, Cthulhu by +# default presents the full line, including any links or form fields on that +# line, in order to reflect the on-screen layout as seen by sighted users. +# Not all users like this presentation, however, and prefer to have objects +# treated as if they were on individual lines, such as is done by Windows +# screen readers, so that unrelated objects (e.g. links in a navbar) are not +# all jumbled together. As a result, this is now configurable. If layout mode +# is enabled, Cthulhu will present the full line as it appears on the screen; if +# it is disabled, Cthulhu will treat each object as if it were on a separate line, +# both for presentation and navigation. This string is associated with the Cthulhu +# command to manually toggle layout mode on/off. +TOGGLE_LAYOUT_MODE = _("Toggle layout mode") + +# Translators: Cthulhu has a number of commands that override the default +# behavior within an application. For instance, on a web page, "h" moves +# you to the next heading. What should happen when you press an "h" in +# an entry on a web page depends: If you want to resume reading content, +# "h" should move to the next heading; if you want to enter text, "h" +# should not move you to the next heading. Similarly, if you are +# at the bottom of an entry and press Down arrow, should you leave the +# entry? Again, it depends on if you want to resume reading content or +# if you are editing the text in the entry. Because Cthulhu doesn't know +# what you want to do, it has two modes: In browse mode, Cthulhu treats +# key presses as commands to read the content; in focus mode, Cthulhu treats +# key presses as something that should be handled by the focused widget. +# This string is associated with the Cthulhu command to manually switch +# between these two modes. +TOGGLE_PRESENTATION_MODE = _("Switch between browse mode and focus mode") + +# Translators: (Please see the previous, detailed translator notes about +# Focus mode and Browse mode.) In order to minimize the amount of work Cthulhu +# users need to do to switch between focus mode and browse mode, Cthulhu attempts +# to automatically switch to the mode which is appropriate to the current +# web element. Sometimes, however, this automatic mode switching is not what +# the user wants. A good example being web apps which have their own keyboard +# navigation and use interaction model. As a result, Cthulhu has a command which +# enables setting a "sticky" focus mode which disables all automatic toggling. +# This string is associated with the Cthulhu command to enable sticky focus mode. +SET_FOCUS_MODE_STICKY = _("Enable sticky focus mode") + +# Translators: (Please see the previous, detailed translator notes about +# Focus mode and Browse mode.) In order to minimize the amount of work Cthulhu +# users need to do to switch between focus mode and browse mode, Cthulhu attempts +# to automatically switch to the mode which is appropriate to the current +# web element. Sometimes, however, this automatic mode switching is not what +# the user wants. A good example being web apps which have their own keyboard +# navigation and use interaction model. As a result, Cthulhu has a command which +# enables setting a "sticky" browse mode which disables all automatic toggling. +# This string is associated with the Cthulhu command to enable sticky browse mode. +SET_BROWSE_MODE_STICKY = _("Enable sticky browse mode") + +# Translators: this is for navigating among unvisited links in a document. +UNVISITED_LINK_PREV = _("Go to previous unvisited link") + +# Translators: this is for navigating among unvisited links in a document. +UNVISITED_LINK_NEXT = _("Go to next unvisited link") + +# Translators: this is for navigating among unvisited links in a document. +UNVISITED_LINK_LIST = _("Display a list of unvisited links") + +# Translators: this is for navigating among visited links in a document. +VISITED_LINK_PREV = _("Go to previous visited link") + +# Translators: this is for navigating among visited links in a document. +VISITED_LINK_NEXT = _("Go to next visited link") + +# Translators: this is for navigating among visited links in a document. +VISITED_LINK_LIST = _("Display a list of visited links") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/colornames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/colornames.py new file mode 100644 index 0000000..c483a85 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/colornames.py @@ -0,0 +1,758 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +from .cthulhu_i18n import C_ + +cssNames = {} + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f0f8ff"] = C_("color name", "alice blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#faebd7"] = C_("color name", "antique white") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#7fffd4"] = C_("color name", "aquamarine") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f0ffff"] = C_("color name", "azure") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f5f5dc"] = C_("color name", "beige") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffe4c4"] = C_("color name", "bisque") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#000000"] = C_("color name", "black") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffebcd"] = C_("color name", "blanched almond") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#0000ff"] = C_("color name", "blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#8a2be2"] = C_("color name", "blue violet") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#a52a2a"] = C_("color name", "brown") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#deb887"] = C_("color name", "burlywood") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#5f9ea0"] = C_("color name", "cadet blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#7fff00"] = C_("color name", "chartreuse") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#d2691e"] = C_("color name", "chocolate") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff7f50"] = C_("color name", "coral") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#6495ed"] = C_("color name", "cornflower blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fff8dc"] = C_("color name", "cornsilk") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#dc143c"] = C_("color name", "crimson") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00ffff"] = C_("color name", "cyan") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00008b"] = C_("color name", "dark blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#008b8b"] = C_("color name", "dark cyan") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#b8860b"] = C_("color name", "dark goldenrod") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#a9a9a9"] = C_("color name", "dark gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#006400"] = C_("color name", "dark green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#bdb76b"] = C_("color name", "dark khaki") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#8b008b"] = C_("color name", "dark magenta") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#556b2f"] = C_("color name", "dark olive green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff8c00"] = C_("color name", "dark orange") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#9932cc"] = C_("color name", "dark orchid") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#8b0000"] = C_("color name", "dark red") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#e9967a"] = C_("color name", "dark salmon") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#8fbc8f"] = C_("color name", "dark sea green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#483d8b"] = C_("color name", "dark slate blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#2f4f4f"] = C_("color name", "dark slate gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00ced1"] = C_("color name", "dark turquoise") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#9400d3"] = C_("color name", "dark violet") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff1493"] = C_("color name", "deep pink") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00bfff"] = C_("color name", "deep sky blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#696969"] = C_("color name", "dim gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#1e90ff"] = C_("color name", "dodger blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#b22222"] = C_("color name", "fire brick") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fffaf0"] = C_("color name", "floral white") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#228b22"] = C_("color name", "forest green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff00ff"] = C_("color name", "fuchsia") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#dcdcdc"] = C_("color name", "gainsboro") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#HTML_color_names. +cssNames["#f8f8ff"] = C_("color name", "ghost white") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffd700"] = C_("color name", "gold") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#daa520"] = C_("color name", "goldenrod") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#808080"] = C_("color name", "gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#008000"] = C_("color name", "green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#adff2f"] = C_("color name", "green yellow") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f0fff0"] = C_("color name", "honeydew") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff69b4"] = C_("color name", "hot pink") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#cd5c5c"] = C_("color name", "indian red") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#4b0082"] = C_("color name", "indigo") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fffff0"] = C_("color name", "ivory") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f0e68c"] = C_("color name", "khaki") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#e6e6fa"] = C_("color name", "lavender") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fff0f5"] = C_("color name", "lavender blush") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#7cfc00"] = C_("color name", "lawn green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fffacd"] = C_("color name", "lemon chiffon") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#add8e6"] = C_("color name", "light blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f08080"] = C_("color name", "light coral") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#e0ffff"] = C_("color name", "light cyan") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fafad2"] = C_("color name", "light goldenrod yellow") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#d3d3d3"] = C_("color name", "light gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#90ee90"] = C_("color name", "light green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffb6c1"] = C_("color name", "light pink") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffa07a"] = C_("color name", "light salmon") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#20b2aa"] = C_("color name", "light sea green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#87cefa"] = C_("color name", "light sky blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#778899"] = C_("color name", "light slate gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#b0c4de"] = C_("color name", "light steel blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffffe0"] = C_("color name", "light yellow") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00ff00"] = C_("color name", "lime") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#32cd32"] = C_("color name", "lime green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#faf0e6"] = C_("color name", "linen") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff00ff"] = C_("color name", "magenta") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#800000"] = C_("color name", "maroon") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#66cdaa"] = C_("color name", "medium aquamarine") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#0000cd"] = C_("color name", "medium blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ba55d3"] = C_("color name", "medium orchid") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#9370d8"] = C_("color name", "medium purple") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#3cb371"] = C_("color name", "medium sea green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#7b68ee"] = C_("color name", "medium slate blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00fa9a"] = C_("color name", "medium spring green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#48d1cc"] = C_("color name", "medium turquoise") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#c71585"] = C_("color name", "medium violet red") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#191970"] = C_("color name", "midnight blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f5fffa"] = C_("color name", "mint cream") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffe4e1"] = C_("color name", "misty rose") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffe4b5"] = C_("color name", "moccasin") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffdead"] = C_("color name", "navajo white") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#000080"] = C_("color name", "navy") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fdf5e6"] = C_("color name", "old lace") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#808000"] = C_("color name", "olive") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#6b8e23"] = C_("color name", "olive drab") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffa500"] = C_("color name", "orange") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff4500"] = C_("color name", "orange red") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#da70d6"] = C_("color name", "orchid") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#eee8aa"] = C_("color name", "pale goldenrod") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#98fb98"] = C_("color name", "pale green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#afeeee"] = C_("color name", "pale turquoise") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#d87093"] = C_("color name", "pale violet red") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffefd5"] = C_("color name", "papaya whip") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffdab9"] = C_("color name", "peach puff") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#cd853f"] = C_("color name", "peru") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffc0cb"] = C_("color name", "pink") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#dda0dd"] = C_("color name", "plum") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#b0e0e6"] = C_("color name", "powder blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#800080"] = C_("color name", "purple") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff0000"] = C_("color name", "red") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#bc8f8f"] = C_("color name", "rosy brown") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#4169e1"] = C_("color name", "royal blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#8b4513"] = C_("color name", "saddle brown") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fa8072"] = C_("color name", "salmon") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f4a460"] = C_("color name", "sandy brown") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#2e8b57"] = C_("color name", "sea green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fff5ee"] = C_("color name", "seashell") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#a0522d"] = C_("color name", "sienna") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#c0c0c0"] = C_("color name", "silver") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#87ceeb"] = C_("color name", "sky blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#6a5acd"] = C_("color name", "slate blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#708090"] = C_("color name", "slate gray") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#fffafa"] = C_("color name", "snow") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#00ff7f"] = C_("color name", "spring green") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#4682b4"] = C_("color name", "steel blue") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#d2b48c"] = C_("color name", "tan") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#008080"] = C_("color name", "teal") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#d8bfd8"] = C_("color name", "thistle") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ff6347"] = C_("color name", "tomato") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#40e0d0"] = C_("color name", "turquoise") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ee82ee"] = C_("color name", "violet") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f5deb3"] = C_("color name", "wheat") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffffff"] = C_("color name", "white") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#f5f5f5"] = C_("color name", "white smoke") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#ffff00"] = C_("color name", "yellow") + +# Translators: This refers to a CSS color name. The name, hex value, and color +# can be found at http://www.w3schools.com/cssref/css_colornames.asp and at +# http://en.wikipedia.org/wiki/Web_colors#X11_color_names. +cssNames["#9acd32"] = C_("color name", "yellow green") + +def rgbToName(red, green, blue): + """Returns the localized name for the RGB value.""" + + hexString = f'#{red:02x}{green:02x}{blue:02x}' + cssName = cssNames.get(hexString) + if cssName: + return cssName + + # Find the closest match. + colors = {} + for key, value in cssNames.items(): + r, g, b = [int(s, 16) for s in (key[1:3], key[3:5], key[5:7])] + rd = abs(r - red) ** 2 + gd = abs(g - green) ** 2 + bd = abs(b - blue) ** 2 + colors[(rd + gd + bd)] = key + + # Hold black and white to higher standards than the other close colors. + d1 = min(colors.keys()) + match = colors.pop(d1) + if match not in ["#000000", "#ffffff"]: + return cssNames.get(match) + + d2 = min(colors.keys()) + if d2 - d1 < d1: + match = colors.pop(d2) + + return cssNames.get(match) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/common_keyboardmap.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/common_keyboardmap.py new file mode 100644 index 0000000..d768a86 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/common_keyboardmap.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" A list of common keybindings and unbound keys + pulled out from default.py: getKeyBindings() + with the goal of being more readable and less monolithic. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010-2011 The Cthulhu Team" +__license__ = "LGPL" + +from . import keybindings + +# Storing values +defaultModifierMask = keybindings.defaultModifierMask +CTHULHU_MODIFIER_MASK = keybindings.CTHULHU_MODIFIER_MASK +NO_MODIFIER_MASK = keybindings.NO_MODIFIER_MASK +CTHULHU_SHIFT_MODIFIER_MASK = keybindings.CTHULHU_SHIFT_MODIFIER_MASK +CTHULHU_CTRL_MODIFIER_MASK = keybindings.CTHULHU_CTRL_MODIFIER_MASK +CTHULHU_ALT_MODIFIER_MASK = keybindings.CTHULHU_ALT_MODIFIER_MASK +CTHULHU_CTRL_ALT_MODIFIER_MASK = keybindings.CTHULHU_CTRL_ALT_MODIFIER_MASK +SHIFT_ALT_MODIFIER_MASK = keybindings.SHIFT_ALT_MODIFIER_MASK + +keymap = ( + + ("space", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "preferencesSettingsHandler"), + + ("space", defaultModifierMask, CTHULHU_CTRL_MODIFIER_MASK, + "appPreferencesSettingsHandler"), + + ("BackSpace", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "bypassNextCommandHandler"), + + ("q", defaultModifierMask, CTHULHU_CTRL_ALT_MODIFIER_MASK | CTHULHU_SHIFT_MODIFIER_MASK, + "toggleSleepModeHandler"), + + ("q", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "shutdownHandler"), + + + ##################################################################### + # # + # Unbound handlers # + # # + ##################################################################### + + ("", defaultModifierMask, NO_MODIFIER_MASK, + "cycleSettingsProfileHandler"), + + ("", defaultModifierMask, NO_MODIFIER_MASK, + "cycleDebugLevelHandler"), + + ("", defaultModifierMask, NO_MODIFIER_MASK, + "panBrailleLeftHandler"), + + ("", defaultModifierMask, NO_MODIFIER_MASK, + "panBrailleRightHandler"), +) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu.py new file mode 100644 index 0000000..a356f5d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu.py @@ -0,0 +1,1183 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""The main module for the Cthulhu screen reader.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2011 The Cthulhu Team" \ + "Copyright (c) 2012 Igalia, S.L." +__license__ = "LGPL" + +import faulthandler + +from . import dbus_service + +class APIHelper: + """Helper class for plugin API interactions, including keybindings.""" + + def __init__(self, app): + """Initialize the APIHelper. + + Arguments: + - app: the Cthulhu application + """ + self.app = app + self._gestureBindings = {} + + def registerGestureByString(self, function, name, gestureString, inputEventType='default', normalizer='cthulhu', learnModeEnabled=True, contextName=None): + """Register a gesture by string.""" + import logging + logger = logging.getLogger(__name__) + + logger.info(f"=== APIHelper.registerGestureByString called ===") + logger.info(f"gestureString: {gestureString}") + logger.info(f"name: {name}") + logger.info(f"contextName: {contextName}") + + if not gestureString.startswith("kb:"): + logger.warning(f"Gesture string doesn't start with 'kb:': {gestureString}") + return None + + # Extract the key portion from the gesture string + key = gestureString.split(":", 1)[1] + logger.info(f"Extracted key: {key}") + + # Handle Cthulhu modifier specially + if "cthulhu+" in key.lower(): + from . import keybindings + key_parts = key.lower().split("+") + logger.info(f"Key parts: {key_parts}") + + # Start with the base Cthulhu modifier + modifiers = keybindings.CTHULHU_MODIFIER_MASK + + # Extract the final key (without modifiers) + final_key = key_parts[-1] + logger.info(f"Final key: {final_key}") + + # Check for additional modifiers and combine them properly + if "control" in key_parts and "shift" in key_parts: + # Combine Cthulhu + Control + Shift modifiers + modifiers = (keybindings.CTHULHU_MODIFIER_MASK | + keybindings.CTRL_MODIFIER_MASK | + keybindings.SHIFT_MODIFIER_MASK) + logger.info(f"Using CTHULHU+CTRL+SHIFT combined mask: {modifiers}") + elif "control" in key_parts: + # Use the pre-defined Cthulhu+Control mask + modifiers = keybindings.CTHULHU_CTRL_MODIFIER_MASK + logger.info(f"Using CTHULHU_CTRL_MODIFIER_MASK: {modifiers}") + elif "shift" in key_parts: + # Use the pre-defined combined mask rather than trying to OR them + modifiers = keybindings.CTHULHU_SHIFT_MODIFIER_MASK + logger.info(f"Using CTHULHU_SHIFT_MODIFIER_MASK: {modifiers}") + else: + logger.info(f"Using CTHULHU_MODIFIER_MASK: {modifiers}") + + # Create a keybinding handler + class GestureHandler: + def __init__(self, function, description, learnModeEnabled=True): + self.function = function + self.description = description + self.learnModeEnabled = learnModeEnabled + + def __call__(self, script, inputEvent): + try: + logger.info(f"=== Plugin keybinding handler called! ===") + return function(script, inputEvent) + except Exception as e: + import logging + logging.getLogger(__name__).error(f"Error in keybinding handler: {e}") + return True + + handler = GestureHandler(function, name, learnModeEnabled) + logger.info(f"Created handler: {handler}") + + # Create the binding object regardless of whether there's an active script + # This allows plugins to define bindings that will work when a script becomes active + from . import cthulhu_state + from . import keybindings + binding = keybindings.KeyBinding( + final_key, + keybindings.defaultModifierMask, + modifiers, + handler) + + logger.info(f"Created binding: keysym={binding.keysymstring}, modifiers={binding.modifiers}, mask={binding.modifier_mask}") + + # Store binding for later reference + if contextName not in self._gestureBindings: + self._gestureBindings[contextName] = [] + self._gestureBindings[contextName].append(binding) + logger.info(f"Stored binding in context '{contextName}'") + + # Only add to active script if one exists + if cthulhu_state.activeScript: + logger.info(f"Adding binding to active script: {cthulhu_state.activeScript}") + bindings = cthulhu_state.activeScript.getKeyBindings() + bindings.add(binding) + + # Register key grab at the system level + grab_ids = addKeyGrab(binding) + logger.info(f"Key grab IDs: {grab_ids}") + + # For later removal + if grab_ids: + binding._grab_ids = grab_ids + else: + debug.printMessage(debug.LEVEL_INFO, "No active script available - binding stored for later registration", True) + + debug.printMessage(debug.LEVEL_INFO, f"Created binding: {binding.keysymstring} with modifiers {binding.modifiers}", True) + logger.info("=== APIHelper.registerGestureByString completed ===") + return binding + else: + logger.warning(f"Key doesn't contain 'cthulhu+': {key}") + + return None + + def unregisterShortcut(self, binding, contextName=None): + """Unregister a previously registered shortcut. + + Arguments: + - binding: the binding to unregister + - contextName: the context for this gesture + """ + # Remove from script's keybindings + from . import cthulhu_state + if cthulhu_state.activeScript: + bindings = cthulhu_state.activeScript.getKeyBindings() + bindings.remove(binding) + + # Remove key grab at system level + if hasattr(binding, '_grab_ids'): + for grab_id in binding._grab_ids: + self.app.removeKeyGrab(grab_id) + + # Remove from tracking + if contextName in self._gestureBindings: + if binding in self._gestureBindings[contextName]: + self._gestureBindings[contextName].remove(binding) + + +import gi +import importlib +import os +import re +import signal +import subprocess +import sys + +gi.require_version("Atspi", "2.0") +gi.require_version("Gdk", "3.0") +from gi.repository import Atspi +from gi.repository import Gdk +from gi.repository import GObject + +try: + from gi.repository.Gio import Settings + a11yAppSettings = Settings(schema_id='org.gnome.desktop.a11y.applications') +except Exception: + a11yAppSettings = None + +from . import braille +from . import debug +from . import event_manager +from . import keybindings +from . import learn_mode_presenter +from . import logger +from . import messages +from . import notification_presenter +from . import cthulhu_state +from . import cthulhu_platform +from . import script_manager +from . import settings +from . import settings_manager +from . import speech +from . import sound +from . import mouse_review +from .ax_object import AXObject +from .ax_utilities import AXUtilities +# Lazy import to avoid circular dependency +# from .input_event import BrailleEvent +from . import cmdnames +from . import plugin_system_manager # This will now be your pluggy-based implementation +from . import guilabels +from . import acss +from . import text_attribute_names +from . import speechserver +from . import input_event +from . import pronunciation_dict +from . import cthulhu_gtkbuilder +from . import signal_manager +from . import dynamic_api_manager +from . import translation_manager +from . import resource_manager + + +_eventManager = event_manager.getManager() +_scriptManager = script_manager.getManager() +_settingsManager = settings_manager.getManager() +_logger = logger.getLogger() + +def onEnabledChanged(gsetting, key): + try: + enabled = gsetting.get_boolean(key) + except Exception: + return + + if key == 'screen-reader-enabled' and not enabled: + shutdown() + +def getSettingsManager(): + return _settingsManager + +def getLogger(): + return _logger + +EXIT_CODE_HANG = 50 + +# The user-settings module (see loadUserSettings). +# +_userSettings = None + +# A subset of the original Xmodmap info prior to our stomping on it. +# Right now, this is just for the user's chosen Cthulhu modifier(s). +# +_originalXmodmap = "" +_cthulhuModifiers = settings.DESKTOP_MODIFIER_KEYS + settings.LAPTOP_MODIFIER_KEYS +_capsLockCleared = False +_restoreCthulhuKeys = False + +######################################################################## +# # +# METHODS TO HANDLE APPLICATION LIST AND FOCUSED OBJECTS # +# # +######################################################################## + +CARET_TRACKING = "caret-tracking" +FOCUS_TRACKING = "focus-tracking" +FLAT_REVIEW = "flat-review" +MOUSE_REVIEW = "mouse-review" +OBJECT_NAVIGATOR = "object-navigator" +SAY_ALL = "say-all" + +def getActiveModeAndObjectOfInterest(): + tokens = ["CTHULHU: Active mode:", cthulhu_state.activeMode, + "Object of interest:", cthulhu_state.objOfInterest] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return cthulhu_state.activeMode, cthulhu_state.objOfInterest + +def emitRegionChanged(obj, startOffset=None, endOffset=None, mode=None): + """Notifies interested clients that the current region of interest has changed.""" + + if startOffset is None: + startOffset = 0 + if endOffset is None: + endOffset = startOffset + if mode is None: + mode = FOCUS_TRACKING + + try: + obj.emit("mode-changed::" + mode, 1, "") + except Exception: + msg = "CTHULHU: Exception emitting mode-changed notification" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if mode != cthulhu_state.activeMode: + tokens = ["CTHULHU: Switching active mode from", cthulhu_state.activeMode, "to", mode] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu_state.activeMode = mode + + try: + tokens = ["CTHULHU: Region of interest:", obj, "(", startOffset, ")", endOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj.emit("region-changed", startOffset, endOffset) + except Exception: + msg = "CTHULHU: Exception emitting region-changed notification" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if obj != cthulhu_state.objOfInterest: + tokens = ["CTHULHU: Switching object of interest from", cthulhu_state.objOfInterest, "to", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu_state.objOfInterest = obj + +def setActiveWindow(frame, app=None, alsoSetLocusOfFocus=False, notifyScript=False): + tokens = ["CTHULHU: Request to set active window to", frame] + if app is not None: + tokens.extend(["in", app]) + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if frame == cthulhu_state.activeWindow: + msg = "CTHULHU: Setting activeWindow to existing activeWindow" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif frame is None: + cthulhu_state.activeWindow = None + else: + real_app, real_frame = AXObject.find_real_app_and_window_for(frame, app) + if real_frame != frame: + tokens = ["CTHULHU: Correcting active window to", real_frame, "in", real_app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu_state.activeWindow = real_frame + else: + cthulhu_state.activeWindow = frame + + if alsoSetLocusOfFocus: + setLocusOfFocus(None, cthulhu_state.activeWindow, notifyScript=notifyScript) + +def setLocusOfFocus(event, obj, notifyScript=True, force=False): + """Sets the locus of focus (i.e., the object with visual focus) and + notifies the script of the change should the script wish to present + the change to the user. + + Arguments: + - event: if not None, the Event that caused this to happen + - obj: the Accessible with the new locus of focus. + - notifyScript: if True, propagate this event + - force: if True, don't worry if this is the same object as the + current locusOfFocus + """ + + if not force and obj == cthulhu_state.locusOfFocus: + msg = "CTHULHU: Setting locusOfFocus to existing locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if event and (cthulhu_state.activeScript and not cthulhu_state.activeScript.app): + app = AXObject.get_application(event.source) + script = _scriptManager.getScript(app, event.source) + _scriptManager.setActiveScript(script, "Setting locusOfFocus") + + oldFocus = cthulhu_state.locusOfFocus + if AXObject.is_dead(oldFocus): + oldFocus = None + + if obj is None: + msg = "CTHULHU: New locusOfFocus is null (being cleared)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu_state.locusOfFocus = None + return + + if cthulhu_state.activeScript: + tokens = ["CTHULHU: Active script is:", cthulhu_state.activeScript] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if cthulhu_state.activeScript.utilities.isZombie(obj): + tokens = ["ERROR: New locusOfFocus (", obj, ") is zombie. Not updating."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + if AXObject.is_dead(obj): + tokens = ["ERROR: New locusOfFocus (", obj, ") is dead. Not updating."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + tokens = ["CTHULHU: Changing locusOfFocus from", oldFocus, "to", obj, ". Notify:", notifyScript] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu_state.locusOfFocus = obj + + if not notifyScript: + return + + if not cthulhu_state.activeScript: + msg = "CTHULHU: Cannot notify active script because there isn't one" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + cthulhu_state.activeScript.locusOfFocusChanged(event, oldFocus, cthulhu_state.locusOfFocus) + +######################################################################## +# # +# METHODS FOR PRE-PROCESSING AND MASSAGING BRAILLE EVENTS. # +# # +######################################################################## + +def _processBrailleEvent(event): + """Called whenever a key is pressed on the Braille display. + + Arguments: + - command: the BrlAPI event for the key that was pressed. + + Returns True if the event was consumed; otherwise False + """ + + consumed = False + + # Braille key presses always interrupt speech. + # + # Lazy import to avoid circular dependency + from .input_event import BrailleEvent + event = BrailleEvent(event) + if event.event['command'] not in braille.dontInteruptSpeechKeys: + speech.stop() + cthulhu_state.lastInputEvent = event + + try: + consumed = _eventManager.processBrailleEvent(event) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + # TODO - JD: Is this still possible? + if not consumed and learn_mode_presenter.getPresenter().is_active(): + consumed = True + + return consumed + +######################################################################## +# # +# METHODS FOR HANDLING INITIALIZATION, SHUTDOWN, AND USE. # +# # +######################################################################## + +def deviceChangeHandler(deviceManager, device): + """New keyboards being plugged in stomp on our changes to the keymappings, + so we have to re-apply""" + source = device.get_source() + if source == Gdk.InputSource.KEYBOARD: + msg = "CTHULHU: Keyboard change detected, re-creating the xmodmap" + debug.printMessage(debug.LEVEL_INFO, msg, True) + _createCthulhuXmodmap() + +def updateKeyMap(keyboardEvent): + """Unsupported convenience method to call sad hacks which should go away.""" + + global _restoreCthulhuKeys + if keyboardEvent.isPressedKey(): + return + + if keyboardEvent.event_string in settings.cthulhuModifierKeys \ + and cthulhu_state.bypassNextCommand: + _restoreXmodmap() + _restoreCthulhuKeys = True + return + + if _restoreCthulhuKeys and not cthulhu_state.bypassNextCommand: + _createCthulhuXmodmap() + _restoreCthulhuKeys = False + +def _setXmodmap(xkbmap): + """Set the keyboard map using xkbcomp.""" + p = subprocess.Popen(['xkbcomp', '-w0', '-', os.environ['DISPLAY']], + stdin=subprocess.PIPE, stdout=None, stderr=None) + p.communicate(xkbmap) + +def _setCapsLockAsCthulhuModifier(enable): + """Enable or disable use of the caps lock key as an Cthulhu modifier key.""" + interpretCapsLineProg = re.compile( + r'^\s*interpret\s+Caps[_+]Lock[_+]AnyOfOrNone\s*\(all\)\s*{\s*$', re.I) + normalCapsLineProg = re.compile( + r'^\s*action\s*=\s*LockMods\s*\(\s*modifiers\s*=\s*Lock\s*\)\s*;\s*$', re.I) + interpretShiftLineProg = re.compile( + r'^\s*interpret\s+Shift[_+]Lock[_+]AnyOf\s*\(\s*Shift\s*\+\s*Lock\s*\)\s*{\s*$', re.I) + normalShiftLineProg = re.compile( + r'^\s*action\s*=\s*LockMods\s*\(\s*modifiers\s*=\s*Shift\s*\)\s*;\s*$', re.I) + disabledModLineProg = re.compile( + r'^\s*action\s*=\s*NoAction\s*\(\s*\)\s*;\s*$', re.I) + normalCapsLine = ' action= LockMods(modifiers=Lock);' + normalShiftLine = ' action= LockMods(modifiers=Shift);' + disabledModLine = ' action= NoAction();' + lines = _originalXmodmap.decode('UTF-8').split('\n') + foundCapsInterpretSection = False + foundShiftInterpretSection = False + modified = False + for i, line in enumerate(lines): + if not foundCapsInterpretSection and not foundShiftInterpretSection: + if interpretCapsLineProg.match(line): + foundCapsInterpretSection = True + elif interpretShiftLineProg.match(line): + foundShiftInterpretSection = True + elif foundCapsInterpretSection: + if enable: + if normalCapsLineProg.match(line): + lines[i] = disabledModLine + modified = True + else: + if disabledModLineProg.match(line): + lines[i] = normalCapsLine + modified = True + if line.find('}'): + foundCapsInterpretSection = False + else: # foundShiftInterpretSection + if enable: + if normalShiftLineProg.match(line): + lines[i] = disabledModLine + modified = True + else: + if disabledModLineProg.match(line): + lines[i] = normalShiftLine + modified = True + if line.find('}'): + foundShiftInterpretSection = False + if modified: + _setXmodmap(bytes('\n'.join(lines), 'UTF-8')) + +def _createCthulhuXmodmap(): + """Makes an Cthulhu-specific Xmodmap so that the keys behave as we + need them to do. This is especially the case for the Cthulhu modifier. + """ + + global _capsLockCleared + + if "Caps_Lock" in settings.cthulhuModifierKeys \ + or "Shift_Lock" in settings.cthulhuModifierKeys: + _setCapsLockAsCthulhuModifier(True) + _capsLockCleared = True + elif _capsLockCleared: + _setCapsLockAsCthulhuModifier(False) + _capsLockCleared = False + +def _storeXmodmap(keyList): + """Save the original xmodmap for the keys in keyList before we alter it. + + Arguments: + - keyList: A list of named keys to look for. + """ + + global _originalXmodmap + _originalXmodmap = subprocess.check_output(['xkbcomp', os.environ['DISPLAY'], '-']) + +def _restoreXmodmap(keyList=[]): + """Restore the original xmodmap values for the keys in keyList. + + Arguments: + - keyList: A list of named keys to look for. An empty list means + to restore the entire saved xmodmap. + """ + + msg = "CTHULHU: Attempting to restore original xmodmap" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + global _capsLockCleared + _capsLockCleared = False + p = subprocess.Popen(['xkbcomp', '-w0', '-', os.environ['DISPLAY']], + stdin=subprocess.PIPE, stdout=None, stderr=None) + p.communicate(_originalXmodmap) + + msg = "CTHULHU: Original xmodmap restored" + debug.printMessage(debug.LEVEL_INFO, msg, True) + +def setKeyHandling(new): + """Toggle use of the new vs. legacy key handling mode. + """ + _eventManager.setKeyHandling(new) + +def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False): + """Loads (and reloads) the user settings module, reinitializing + things such as speech if necessary. + + Returns True to indicate the input event has been consumed. + """ + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Loading User Settings', True) + + global _userSettings + + # Shutdown the output drivers and give them a chance to die. + + player = sound.getPlayer() + player.shutdown() + speech.shutdown() + braille.shutdown() + + _scriptManager.deactivate() + cthulhuApp.getSignalManager().emitSignal('load-setting-begin') + + reloaded = False + if _userSettings: + _profile = _settingsManager.getSetting('activeProfile')[1] + try: + _userSettings = _settingsManager.getGeneralSettings(_profile) + _settingsManager.setProfile(_profile) + reloaded = True + except ImportError: + debug.printException(debug.LEVEL_INFO) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + else: + _profile = _settingsManager.profile + try: + _userSettings = _settingsManager.getGeneralSettings(_profile) + except ImportError: + debug.printException(debug.LEVEL_INFO) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + if not script: + script = _scriptManager.getDefaultScript() + + _settingsManager.loadAppSettings(script) + + if _settingsManager.getSetting('enableSpeech'): + msg = 'CTHULHU: About to enable speech' + debug.printMessage(debug.LEVEL_INFO, msg, True) + try: + speech.init() + if reloaded and not skipReloadMessage: + script.speakMessage(messages.SETTINGS_RELOADED) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + else: + msg = 'CTHULHU: Speech is not enabled in settings' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if _settingsManager.getSetting('enableBraille'): + msg = 'CTHULHU: About to enable braille' + debug.printMessage(debug.LEVEL_INFO, msg, True) + try: + braille.init(_processBrailleEvent) + except Exception: + debug.printException(debug.LEVEL_WARNING) + msg = 'CTHULHU: Could not initialize connection to braille.' + debug.printMessage(debug.LEVEL_WARNING, msg, True) + else: + msg = 'CTHULHU: Braille is not enabled in settings' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + + if _settingsManager.getSetting('enableMouseReview'): + mouse_review.getReviewer().activate() + else: + mouse_review.getReviewer().deactivate() + + if _settingsManager.getSetting('enableSound'): + player.init() + + global _cthulhuModifiers + custom = [k for k in settings.cthulhuModifierKeys if k not in _cthulhuModifiers] + _cthulhuModifiers += custom + # Handle the case where a change was made in the Cthulhu Preferences dialog. + # + if _originalXmodmap: + _restoreXmodmap(_cthulhuModifiers) + + _storeXmodmap(_cthulhuModifiers) + _createCthulhuXmodmap() + + # Activate core systems FIRST before loading plugins + _scriptManager.activate() + _eventManager.activate() + + cthulhuApp.getSignalManager().emitSignal('load-setting-begin') + + # NOW load plugins after script system is ready + activePlugins = list(_settingsManager.getSetting('activePlugins')) + debug.printMessage(debug.LEVEL_INFO, f'CTHULHU: Loading active plugins: {activePlugins}', True) + cthulhuApp.getPluginSystemManager().setActivePlugins(activePlugins) + + # Refresh keybindings to include plugin bindings (after script manager is active) + cthulhuApp.getPluginSystemManager().refresh_active_script_keybindings() + + cthulhuApp.getSignalManager().emitSignal('load-setting-completed') + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: User Settings Loaded', True) + + return True + +def _showPreferencesUI(script, prefs): + if cthulhu_state.cthulhuOS: + cthulhu_state.cthulhuOS.showGUI() + return + + try: + module = importlib.import_module('.cthulhu_gui_prefs', 'cthulhu') + except Exception: + debug.printException(debug.LEVEL_SEVERE) + return + + uiFile = os.path.join(cthulhu_platform.datadir, + cthulhu_platform.package, + "ui", + "cthulhu-setup.ui") + + cthulhu_state.cthulhuOS = module.CthulhuSetupGUI(uiFile, "cthulhuSetupWindow", prefs) + cthulhu_state.cthulhuOS.init(script) + cthulhu_state.cthulhuOS.showGUI() + +def showAppPreferencesGUI(script=None, inputEvent=None): + """Displays the user interface to configure the settings for a + specific applications within Cthulhu and set up those app-specific + user preferences using a GUI. + + Returns True to indicate the input event has been consumed. + """ + + prefs = {} + for key in settings.userCustomizableSettings: + prefs[key] = _settingsManager.getSetting(key) + + script = script or cthulhu_state.activeScript + _showPreferencesUI(script, prefs) + + return True + +def showPreferencesGUI(script=None, inputEvent=None): + """Displays the user interface to configure Cthulhu and set up + user preferences using a GUI. + + Returns True to indicate the input event has been consumed. + """ + + prefs = _settingsManager.getGeneralSettings(_settingsManager.profile) + script = _scriptManager.getDefaultScript() + _showPreferencesUI(script, prefs) + + return True + +def addKeyGrab(binding): + """ Add a key grab for the given key binding.""" + + if cthulhu_state.device is None: + return [] + + ret = [] + for kd in binding.keyDefs(): + ret.append(cthulhu_state.device.add_key_grab(kd, None)) + return ret + +def removeKeyGrab(id): + """ Remove the key grab for the given key binding.""" + + if cthulhu_state.device is None: + return + + cthulhu_state.device.remove_key_grab(id) + +def mapModifier(keycode): + if cthulhu_state.device is None: + return + + return cthulhu_state.device.map_modifier(keycode) + +def quitCthulhu(script=None, inputEvent=None): + """Quit Cthulhu. Check if the user wants to confirm this action. + If so, show the confirmation GUI otherwise just shutdown. + + Returns True to indicate the input event has been consumed. + """ + + shutdown() + + return True + +def showFindGUI(script=None, inputEvent=None): + """Displays the user interface to perform an Cthulhu Find. + + Returns True to indicate the input event has been consumed. + """ + + try: + module = importlib.import_module('.cthulhu_gui_find', 'cthulhu') + module.showFindUI() + except Exception: + debug.printException(debug.LEVEL_SEVERE) + +# If True, this module has been initialized. +# +_initialized = False + +def init(): + """Initialize the cthulhu module, which initializes the speech and braille + modules. Also builds up the application list, registers for AT-SPI events, + and creates scripts for all known applications. + + Returns True if the initialization procedure has run, or False if this + module has already been initialized. + """ + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Initializing', True) + + global _initialized + + if _initialized and _settingsManager.isScreenReaderServiceEnabled(): + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Already initialized', True) + return False + + # Do not hang on initialization if we can help it. + # + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.signal(signal.SIGALRM, settings.timeoutCallback) + signal.alarm(settings.timeoutTime) + + # Activate settings manager before loading user settings + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Activating settings manager', True) + _settingsManager.activate() + + loadUserSettings() + + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.alarm(0) + + _initialized = True + # In theory, we can do this through dbus. In practice, it fails to + # work sometimes. Until we know why, we need to leave this as-is + # so that we respond when gnome-control-center is used to stop Cthulhu. + if a11yAppSettings: + a11yAppSettings.connect('changed', onEnabledChanged) + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Initialized', True) + + return True + +def _start_dbus_service(): + """Starts the D-Bus remote controller service in an idle callback.""" + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Starting D-Bus remote controller', True) + try: + dbus_service.get_remote_controller().start() + except Exception as e: + msg = f"CTHULHU: Failed to start D-Bus service: {e}" + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + return False # Remove the idle callback + +def start(): + """Starts Cthulhu.""" + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Starting', True) + + if not _initialized: + init() + + # Do not hang on startup if we can help it. + # + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.signal(signal.SIGALRM, settings.timeoutCallback) + signal.alarm(settings.timeoutTime) + + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.alarm(0) + + # Event handlers for input devices being plugged in/unplugged. + # Used to re-create the Xmodmap when a new keyboard is plugged in. + # Necessary, because plugging in a new keyboard resets the Xmodmap + # and stomps our changes + display = Gdk.Display.get_default() + devmanager=display.get_device_manager() + devmanager.connect("device-added", deviceChangeHandler) + devmanager.connect("device-removed", deviceChangeHandler) + + Gdk.notify_startup_complete() + msg = 'CTHULHU: Startup complete notification made' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Starting Atspi main event loop', True) + + # Start D-Bus remote controller service after ATSPI is ready + GObject.idle_add(_start_dbus_service) + + Atspi.event_main() + +def die(exitCode=1): + pid = os.getpid() + if exitCode == EXIT_CODE_HANG: + # Someting is hung and we wish to abort. + os.kill(pid, signal.SIGKILL) + return + + shutdown() + sys.exit(exitCode) + if exitCode > 1: + os.kill(pid, signal.SIGTERM) + +def timeout(signum=None, frame=None): + msg = 'TIMEOUT: something has hung. Aborting.' + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + debug.printStack(debug.LEVEL_SEVERE) + debug.examineProcesses(force=True) + die(EXIT_CODE_HANG) + +def shutdown(script=None, inputEvent=None): + """Exits Cthulhu. Unregisters any event listeners and cleans up. + + Returns True if the shutdown procedure ran or False if this module + was never initialized. + """ + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Shutting down', True) + + # Shutdown D-Bus remote controller service early + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Shutting down D-Bus remote controller', True) + dbus_service.get_remote_controller().shutdown() + + global _initialized + + if not _initialized: + return False + + # Try to say goodbye, but be defensive if something has hung. + # + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.signal(signal.SIGALRM, settings.timeoutCallback) + signal.alarm(settings.timeoutTime) + + cthulhu_state.activeScript.presentationInterrupt() + + cthulhuApp.getSignalManager().emitSignal('stop-application-completed') + cthulhuApp.getPluginSystemManager().unloadAllPlugins(ForceAllPlugins=True) + + # Deactivate the event manager first so that it clears its queue and will not + # accept new events. Then let the script manager unregister script event listeners. + _eventManager.deactivate() + _scriptManager.deactivate() + + # Shutdown all the other support. + # + if settings.enableSpeech: + speech.shutdown() + if settings.enableBraille: + braille.shutdown() + if settings.enableSound: + player = sound.getPlayer() + player.shutdown() + + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.alarm(0) + + _initialized = False + _restoreXmodmap(_cthulhuModifiers) + + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Quitting Atspi main event loop', True) + Atspi.event_quit() + debug.printMessage(debug.LEVEL_INFO, 'CTHULHU: Shutdown complete', True) + + return True + +exitCount = 0 +def shutdownOnSignal(signum, frame): + global exitCount + + signalString = f'({signal.strsignal(signum)})' + msg = f"CTHULHU: Shutting down and exiting due to signal={signum} {signalString}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # Well...we'll try to exit nicely, but if we keep getting called, + # something bad is happening, so just quit. + # + if exitCount: + die(signum) + else: + exitCount += 1 + + # Try to do a graceful shutdown if we can. + # + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.signal(signal.SIGALRM, settings.timeoutCallback) + signal.alarm(settings.timeoutTime) + + try: + if _initialized: + shutdown() + else: + # We always want to try to shutdown speech since the + # speech servers are very persistent about living. + # + speech.shutdown() + shutdown() + cleanExit = True + except Exception: + cleanExit = False + + if settings.timeoutCallback and (settings.timeoutTime > 0): + signal.alarm(0) + + if not cleanExit: + die(EXIT_CODE_HANG) + +def crashOnSignal(signum, frame): + signalString = f'({signal.strsignal(signum)})' + msg = f"CTHULHU: Shutting down and exiting due to signal={signum} {signalString}" + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + debug.printStack(debug.LEVEL_SEVERE) + _restoreXmodmap(_cthulhuModifiers) + sys.exit(1) + +def main(): + """The main entry point for Cthulhu. The exit codes for Cthulhu will + loosely be based on signals, where the exit code will be the + signal used to terminate Cthulhu (if a signal was used). Otherwise, + an exit code of 0 means normal completion and an exit code of 50 + means Cthulhu exited because of a hang.""" + + msg = f"CTHULHU: Launching version {cthulhu_platform.version}" + if cthulhu_platform.revision: + msg += f" (rev {cthulhu_platform.revision})" + + sessionType = os.environ.get('XDG_SESSION_TYPE') or "" + sessionDesktop = os.environ.get('XDG_SESSION_DESKTOP') or "" + session = "%s %s".strip() % (sessionType, sessionDesktop) + if session: + msg += f" session: {session}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if debug.debugFile and os.path.exists(debug.debugFile.name): + faulthandler.enable(file=debug.debugFile, all_threads=True) + else: + faulthandler.enable(all_threads=False) + + # Method to call when we think something might be hung. + # + settings.timeoutCallback = timeout + + # Various signal handlers we want to listen for. + # + signal.signal(signal.SIGHUP, shutdownOnSignal) + signal.signal(signal.SIGINT, shutdownOnSignal) + signal.signal(signal.SIGTERM, shutdownOnSignal) + signal.signal(signal.SIGQUIT, shutdownOnSignal) + signal.signal(signal.SIGSEGV, crashOnSignal) + + debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Enabling accessibility (if needed).", True) + if not _settingsManager.isAccessibilityEnabled(): + _settingsManager.setAccessibility(True) + + debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Initializing.", True) + init() + debug.printMessage(debug.LEVEL_INFO, "CTHULHU: Initialized.", True) + + script = cthulhu_state.activeScript + cthulhuApp.getSignalManager().emitSignal('start-application-completed') + if script: + window = script.utilities.activeWindow() + + if window and not cthulhu_state.locusOfFocus: + app = AXObject.get_application(window) + setActiveWindow(window, app, alsoSetLocusOfFocus=True, notifyScript=True) + + # setActiveWindow does some corrective work needed thanks to + # mutter-x11-frames. So retrieve the window just in case. + window = cthulhu_state.activeWindow + script = _scriptManager.getScript(app, window) + _scriptManager.setActiveScript(script, "Launching.") + + focusedObject = AXUtilities.get_focused_object(window) + tokens = ["CTHULHU: Focused object is:", focusedObject] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if focusedObject: + setLocusOfFocus(None, focusedObject) + script = _scriptManager.getScript( + AXObject.get_application(focusedObject), focusedObject) + _scriptManager.setActiveScript(script, "Found focused object.") + + try: + msg = "CTHULHU: Starting ATSPI registry." + debug.printMessage(debug.LEVEL_INFO, msg, True) + start() # waits until we stop the registry + except Exception: + msg = "CTHULHU: Exception starting ATSPI registry." + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + die(EXIT_CODE_HANG) + return 0 + +class Cthulhu(GObject.Object): + # basic signals + __gsignals__ = { + "start-application-completed": (GObject.SignalFlags.RUN_LAST, None, ()), + "stop-application-completed": (GObject.SignalFlags.RUN_LAST, None, ()), + "load-setting-begin": (GObject.SignalFlags.RUN_LAST, None, ()), + "load-setting-completed": (GObject.SignalFlags.RUN_LAST, None, ()), + "setup-inputeventhandlers-completed": (GObject.SignalFlags.RUN_LAST, None, ()), # compat signal for register input event handlers + "request-cthulhu-preferences": (GObject.SignalFlags.RUN_LAST, None, ()), + "request-application-preferences": (GObject.SignalFlags.RUN_LAST, None, ()), + } + def __init__(self): + GObject.Object.__init__(self) + # add members + self.resourceManager = resource_manager.ResourceManager(self) + self.eventManager = _eventManager + self.settingsManager = _settingsManager + self.scriptManager = _scriptManager + self.signalManager = signal_manager.SignalManager(self) + self.dynamicApiManager = dynamic_api_manager.DynamicApiManager(self) + self.translationManager = translation_manager.TranslationManager(self) + self.debugManager = debug + self.APIHelper = APIHelper(self) + self.createCompatAPI() + self.pluginSystemManager = plugin_system_manager.PluginSystemManager(self) + # Scan for available plugins at startup + self.pluginSystemManager.rescanPlugins() + def getAPIHelper(self): + return self.APIHelper + def getPluginSystemManager(self): + return self.pluginSystemManager + def getDynamicApiManager(self): + return self.dynamicApiManager + def getSignalManager(self): + return self.signalManager + def getEventManager(self): + return self.eventManager + def getSettingsManager(self): + return self.settingsManager + def getScriptManager(self): + return self.scriptManager + def getDebugManager(self): + return self.debugManager + def getTranslationManager(self): + return self.translationManager + def getResourceManager(self): + return self.resourceManager + def run(self, cacheValues=True): + return main(cacheValues) + def stop(self): + pass + def createCompatAPI(self): + # for now add compatibility layer using Dynamic API + # should be removed step by step + # use clean objects, getters and setters instead + + self.getDynamicApiManager().registerAPI('Logger', _logger) + self.getDynamicApiManager().registerAPI('SettingsManager', settings_manager) + self.getDynamicApiManager().registerAPI('ScriptManager', script_manager) + self.getDynamicApiManager().registerAPI('EventManager', event_manager) + self.getDynamicApiManager().registerAPI('Speech', speech) + self.getDynamicApiManager().registerAPI('Sound', sound) + self.getDynamicApiManager().registerAPI('Braille', braille) + self.getDynamicApiManager().registerAPI('Debug', debug) + self.getDynamicApiManager().registerAPI('Messages', messages) + self.getDynamicApiManager().registerAPI('Cmdnames', cmdnames) + self.getDynamicApiManager().registerAPI('NotificationPresenter', notification_presenter) + self.getDynamicApiManager().registerAPI('CthulhuState', cthulhu_state) + self.getDynamicApiManager().registerAPI('CthulhuPlatform', cthulhu_platform) + self.getDynamicApiManager().registerAPI('Settings', settings) + self.getDynamicApiManager().registerAPI('Keybindings', keybindings) + self.getDynamicApiManager().registerAPI('GuiLabels', guilabels) + self.getDynamicApiManager().registerAPI('Acss', acss) + self.getDynamicApiManager().registerAPI('TextAttributeNames', text_attribute_names) + self.getDynamicApiManager().registerAPI('PronunciationDict', pronunciation_dict) + self.getDynamicApiManager().registerAPI('InputEvent', input_event) + self.getDynamicApiManager().registerAPI('SpeechServer', speechserver) + self.getDynamicApiManager().registerAPI('CthulhuGtkbuilder', cthulhu_gtkbuilder) + self.getDynamicApiManager().registerAPI('AXObject', AXObject) + self.getDynamicApiManager().registerAPI('AXUtilities', AXUtilities) + self.getDynamicApiManager().registerAPI('LearnModePresenter', learn_mode_presenter) + # cthulhu lets say, special compat handling.... + self.getDynamicApiManager().registerAPI('EmitRegionChanged', emitRegionChanged) + self.getDynamicApiManager().registerAPI('LoadUserSettings', loadUserSettings) + self.getDynamicApiManager().registerAPI('APIHelper', self.APIHelper) + +cthulhuApp = Cthulhu() + +def getManager(): + return cthulhuApp + +if __name__ == "__main__": + GObject.threads_init() + sys.exit(cthulhuApp.run()) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhuVersion.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhuVersion.py new file mode 100644 index 0000000..5a95374 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhuVersion.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +version = "2025.08.11" +codeName = "testing" diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_bin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_bin.py new file mode 100644 index 0000000..9d80aab --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_bin.py @@ -0,0 +1,278 @@ +#!/home/storm/.pyenv/shims/python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import argparse +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +import os +import signal +import subprocess +import sys +import time + +sys.prefix = '/usr' +pythondir = '/usr/lib/python3.13/site-packages/' +pythondir = pythondir.replace('${PYTHON_PREFIX}', '/usr/lib/python3.13/site-packages/') +pythondir = pythondir.replace('${prefix}', '/usr') +sys.path.insert(1, pythondir) + +# Do not import Cthulhu here. It is imported in main(). The reason why is that +# start-up failures due to imports in cthulhu.py are not getting output, making +# them challenging to debug when they cannot be reproduced locally. + +from cthulhu import debug +from cthulhu import messages +from cthulhu import settings +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities +from cthulhu.cthulhu_platform import version + +class ListApps(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + desktop = AXUtilities.get_desktop() + for app in AXObject.iter_children(desktop): + pid = AXObject.get_process_id(app) + try: + name = Atspi.Accessible.get_name(app) or "(none)" + except Exception: + name = "[DEAD]" + + try: + cmdline = subprocess.getoutput('cat /proc/%s/cmdline' % pid) + except Exception: + cmdline = '(exception encountered)' + else: + cmdline = cmdline.replace('\x00', ' ') + + print(time.strftime('%H:%M:%S', time.localtime()), + ' pid: %5s %-25s %s' % (pid, name, cmdline)) + + parser.exit() + +class Settings(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + settingsDict = getattr(namespace, 'settings', {}) + invalid = getattr(namespace, 'invalid', []) + for value in values.split(','): + item = str.title(value).replace('-', '') + try: + test = 'enable%s' % item + eval('settings.%s' % test) + except AttributeError: + try: + test = 'show%s' % item + eval('settings.%s' % test) + except AttributeError: + invalid.append(value) + continue + settingsDict[test] = self.const + setattr(namespace, 'settings', settingsDict) + setattr(namespace, 'invalid', invalid) + +class HelpFormatter(argparse.HelpFormatter): + def __init__(self, prog, indent_increment=2, max_help_position=32, + width=None): + + super().__init__(prog, indent_increment, max_help_position, width) + + def add_usage(self, usage, actions, groups, prefix=None): + super().add_usage(usage, actions, groups, messages.CLI_USAGE) + +class Parser(argparse.ArgumentParser): + def __init__(self, *args, **kwargs): + super(Parser, self).__init__( + epilog=messages.CLI_EPILOG, formatter_class=HelpFormatter, add_help=False) + self.add_argument( + "-h", "--help", action="help", help=messages.CLI_HELP) + self.add_argument( + "-v", "--version", action="version", version=version, help=messages.CLI_VERSION) + self.add_argument( + "-r", "--replace", action="store_true", help=messages.CLI_REPLACE) + self.add_argument( + "-s", "--setup", action="store_true", help=messages.CLI_GUI_SETUP) + self.add_argument( + "-l", "--list-apps", action=ListApps, nargs=0, + help=messages.CLI_LIST_APPS) + self.add_argument( + "-e", "--enable", action=Settings, const=True, + help=messages.CLI_ENABLE_OPTION, metavar=messages.CLI_OPTION) + self.add_argument( + "-d", "--disable", action=Settings, const=False, + help=messages.CLI_DISABLE_OPTION, metavar=messages.CLI_OPTION) + self.add_argument( + "-p", "--profile", action="store", + help=messages.CLI_LOAD_PROFILE, metavar=messages.CLI_PROFILE_NAME) + self.add_argument( + "-u", "--user-prefs", action="store", + help=messages.CLI_LOAD_PREFS, metavar=messages.CLI_PREFS_DIR) + self.add_argument( + "--debug-file", action="store", + help=messages.CLI_DEBUG_FILE, metavar=messages.CLI_DEBUG_FILE_NAME) + self.add_argument( + "--debug", action="store_true", help=messages.CLI_ENABLE_DEBUG) + + self._optionals.title = messages.CLI_OPTIONAL_ARGUMENTS + + def parse_known_args(self, *args, **kwargs): + opts, invalid = super(Parser, self).parse_known_args(*args, **kwargs) + try: + invalid.extend(opts.invalid) + except Exception: + pass + if invalid: + print((messages.CLI_INVALID_OPTIONS + " ".join(invalid))) + + if opts.debug_file: + opts.debug = True + elif opts.debug: + opts.debug_file = time.strftime('debug-%Y-%m-%d-%H:%M:%S.out') + + return opts, invalid + +def setProcessName(name): + """Attempts to set the process name to the specified name.""" + + sys.argv[0] = name + + try: + from setproctitle import setproctitle + except ImportError: + pass + else: + setproctitle(name) + return True + + try: + from ctypes import cdll, byref, create_string_buffer + libc = cdll.LoadLibrary('libc.so.6') + stringBuffer = create_string_buffer(len(name) + 1) + stringBuffer.value = bytes(name, 'UTF-8') + libc.prctl(15, byref(stringBuffer), 0, 0, 0) + return True + except Exception: + pass + + return False + +def inGraphicalDesktop(): + """Returns True if we are in a graphical desktop.""" + + # TODO - JD: Make this desktop environment agnostic + try: + import gi + gi.require_version("Gdk", "3.0") + from gi.repository import Gdk + display = Gdk.Display.get_default() + except Exception: + return False + + return display is not None + +def otherCthulhus(): + """Returns the pid of any other instances of Cthulhu owned by this user.""" + + openFile = subprocess.Popen('pgrep -u %s -x cthulhu' % os.getuid(), + shell=True, + stdout=subprocess.PIPE).stdout + pids = openFile.read() + openFile.close() + cthulhus = [int(p) for p in pids.split()] + + pid = os.getpid() + return [p for p in cthulhus if p != pid] + +def cleanup(sigval): + """Tries to clean up any other running Cthulhu instances owned by this user.""" + + cthulhusToKill = otherCthulhus() + debug.printMessage(debug.LEVEL_INFO, "INFO: Cleaning up these PIDs: %s" % cthulhusToKill) + + def onTimeout(signum, frame): + cthulhusToKill = otherCthulhus() + debug.printMessage(debug.LEVEL_INFO, "INFO: Timeout cleaning up: %s" % cthulhusToKill) + for pid in cthulhusToKill: + os.kill(pid, signal.SIGKILL) + + for pid in cthulhusToKill: + os.kill(pid, sigval) + signal.signal(signal.SIGALRM, onTimeout) + signal.alarm(2) + while otherCthulhus(): + time.sleep(0.5) + +def main(): + setProcessName('cthulhu') + + parser = Parser() + args, invalid = parser.parse_known_args() + + if args.debug: + debug.debugLevel = debug.LEVEL_ALL + debug.eventDebugLevel = debug.LEVEL_OFF + debug.debugFile = open(args.debug_file, 'w') + + if args.replace: + cleanup(signal.SIGKILL) + + settingsDict = getattr(args, 'settings', {}) + + if not inGraphicalDesktop(): + print(messages.CLI_NO_DESKTOP_ERROR) + return 1 + + debug.printMessage(debug.LEVEL_INFO, "INFO: Preparing to launch.", True) + + from cthulhu import cthulhu + manager = cthulhu.getSettingsManager() + + if not manager: + print(messages.CLI_SETTINGS_MANAGER_ERROR) + return 1 + + debug.printMessage(debug.LEVEL_INFO, "INFO: About to activate settings manager.", True) + manager.activate(args.user_prefs, settingsDict) + sys.path.insert(0, manager.getPrefsDir()) + + if args.profile: + try: + manager.setProfile(args.profile) + except Exception: + print(messages.CLI_LOAD_PROFILE_ERROR % args.profile) + manager.setProfile() + + if args.setup: + cleanup(signal.SIGKILL) + cthulhu.showPreferencesGUI() + + if otherCthulhus(): + print(messages.CLI_OTHER_CTHULHUS_ERROR) + return 1 + + debug.printMessage(debug.LEVEL_INFO, "INFO: About to launch Cthulhu.", True) + return cthulhu.main() + +if __name__ == "__main__": + sys.exit(main()) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gtkbuilder.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gtkbuilder.py new file mode 100644 index 0000000..53c80f8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gtkbuilder.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Displays a GUI for the user to quit Cthulhu.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gettext +from gi.repository import Gtk + +from .cthulhu_i18n import _ + +class GtkBuilderWrapper: + """ + Superclass for GtkBuilder based applications. Just derive from this + and your subclass should create methods whose names correspond to + the signal handlers defined in the GtkBuilder file. Any other attributes + in your class will be safely ignored. + + This class will give you the ability to do: + subclass_instance.GtkWindow.method(...) + subclass_instance.widget_name... + """ + + def __init__(self, fileName, windowName): + # Load GtkBuilder file. + self.builder = Gtk.Builder() + self.builder.set_translation_domain(gettext.textdomain()) + self.builder.add_from_file(fileName) + self.gtkWindow = self.builder.get_object(windowName) + + # Force the localization of widgets to work around a GtkBuilder + # bug. See bgo bug 589362. + # + for obj in self.builder.get_objects(): + self.localize_widget(obj) + + # Set default application icon. + self.set_cthulhu_icon() + + instance_attributes = {} + for attribute in dir(self.__class__): + instance_attributes[attribute] = getattr(self, attribute) + self.builder.connect_signals(instance_attributes) + + def set_cthulhu_icon(self): + """Get the icon in all sizes from the current theme and set them as + default for all application windows. + """ + + icon_theme = Gtk.IconTheme.get_default() + try: + icon16 = icon_theme.load_icon("cthulhu", 16, 0) + icon22 = icon_theme.load_icon("cthulhu", 22, 0) + icon24 = icon_theme.load_icon("cthulhu", 24, 0) + icon32 = icon_theme.load_icon("cthulhu", 32, 0) + icon48 = icon_theme.load_icon("cthulhu", 48, 0) + except Exception: + return + else: + Gtk.Window.set_default_icon_list((icon16, + icon22, + icon24, + icon32, + icon48)) + + def get_widget(self, attribute): + """Return the requested widget. This routine has been introduced + (and calls to it made by the Cthulhu GtkBuilder sub-classes), to prevent + "No class attribute" pychecker errors caused when using __getattr__. + + Arguments: + - attribute: name of the widget to return. + """ + + widget = self.builder.get_object(attribute) + if widget is None: + raise AttributeError("Widget [" + attribute + "] not found") + + return widget + + def __getattr__(self, attribute): # Called when no attribute in __dict__ + widget = self.builder.get_object(attribute) + if widget is None: + raise AttributeError("Widget [" + attribute + "] not found") + self.__dict__[attribute] = widget # Add reference to cache. + + return widget + + def localize_widget(self, obj): + """Force the localization of the label/title of GtkBuilder objects + + Arguments: + - obj: the GtkBuilder object whose label or title should be localized + """ + + # TODO - JD: This is a workaround for a GtkBuilder bug which prevents + # the strings displayed by widgets from being translated. See bgo bug + # 589362. + # + try: + useMarkup = obj.get_use_markup() + useUnderline = obj.get_use_underline() + except Exception: + useMarkup = False + useUnderline = False + + if isinstance(obj, Gtk.Frame): + # For some reason, if we localize the frame, which has a label + # but does not (itself) support use_markup, we get unmarked + # labels which are not bold but which do have . If we + # skip the frames, the labels get processed as expected. And + # there was much rejoicing. Yea. + # + return + + try: + title = obj.get_title() + if title and len(title): + obj.set_title(_(title)) + except Exception: + try: + text = obj.get_label() + except Exception: + return False + + if text and len(text): + if useMarkup: + obj.set_markup(_(text)) + else: + obj.set_label(_(text)) + + if useUnderline: + obj.set_use_underline(True) + + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_find.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_find.py new file mode 100644 index 0000000..4aaf088 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_find.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Displays a GUI for the Cthulhu Find window""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import os +import sys +from gi.repository import Gtk +import locale + +from . import find +from . import guilabels +from . import cthulhu_gtkbuilder +from . import cthulhu_state +from . import cthulhu_platform + +OS = None + +class CthulhuFindGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): + + def __init__(self, fileName, windowName): + """Initialize the Cthulhu configuration GUI. + + Arguments: + - fileName: name of the GtkBuilder file. + - windowName: name of the component to get from the GtkBuilder file. + """ + + cthulhu_gtkbuilder.GtkBuilderWrapper.__init__(self, fileName, windowName) + self.activeScript = None + self.caseSensitive = None + self.matchEntireWord = None + self.searchBackwards = None + self.searchString = None + self.startAtTop = None + self.windowWrap = None + + def init(self): + # Initialize the dialog box controls. + self.searchString = "" + self.searchBackwards = False + self.caseSensitive = False + self.matchEntireWord = False + self.windowWrap = True + self.startAtTop = False + + self.activeScript = cthulhu_state.activeScript + + def showGUI(self): + """Show the Cthulhu Find dialog. This assumes that the GUI has + already been created. + """ + + findDialog = self.get_widget("findDialog") + ts = cthulhu_state.lastInputEvent.timestamp + if ts == 0: + ts = Gtk.get_current_event_time() + findDialog.present_with_time(ts) + + # Populate the dialog box from the previous searchQuery, should + # one exist. Note: This is necessary because we are destroying + # the dialog (rather than merely hiding it) before performing the + # search. + + try: + searchForEntry = self.get_widget("searchForEntry") + searchForEntry.set_text(cthulhu_state.searchQuery.searchString) + searchForEntry.select_region(0, len(searchForEntry.get_text())) + if cthulhu_state.searchQuery.startAtTop: + self.get_widget("topRadioButton").set_active(True) + self.get_widget("matchCaseCheckbox").set_active(\ + cthulhu_state.searchQuery.caseSensitive) + self.get_widget("matchEntireWordCheckbox").set_active(\ + cthulhu_state.searchQuery.matchEntireWord) + self.get_widget("wrapAroundCheckbox").set_active(\ + cthulhu_state.searchQuery.windowWrap) + self.get_widget("searchBackwardsCheckbox").set_active(\ + cthulhu_state.searchQuery.searchBackwards) + except Exception: + pass + + def searchForEntryChanged(self, widget): + """Signal handler for the "changed" signal for the + searchForEntry GtkEntry widget. The user has changed + the string to be searched for. + + Arguments: + - widget: the component that generated the signal. + """ + + self.searchString = widget.get_text() + findButton = self.get_widget("findButton") + if len(self.searchString) > 0: + findButton.set_sensitive(True) + else: + findButton.set_sensitive(False) + + def startingPointChanged(self, widget): + """Signal handler for the "toggled" signal for the + currentLocationRadioButton or topRadioButton GtkRadioButton + widgets. The user has toggled the starting point for the search. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.FIND_START_AT_CURRENT_LOCATION: + self.startAtTop = False + else: + self.startAtTop = True + + def matchCaseChecked(self, widget): + """Signal handler for the "toggled" signal for the + matchCaseCheckbox GtkCheckButton widget. The user has + [un]checked the "Match Case" checkbox. + + Arguments: + - widget: the component that generated the signal. + """ + + self.caseSensitive = widget.get_active() + + def matchEntireWordChecked(self, widget): + """Signal handler for the "toggled" signal for the + matchEntireWordCheckbox GtkCheckButton widget. + The user has [un]checked the "Match entire word" + checkbox. + + Arguments: + - widget: the component that generated the signal. + """ + + self.matchEntireWord = widget.get_active() + + def searchBackwardsChecked(self, widget): + """Signal handler for the "toggled" signal for the + searchBackwardsCheckbox GtkCheckButton widget. + The user has [un]checked the "Search backwards" + checkbox. + + Arguments: + - widget: the component that generated the signal. + """ + + self.searchBackwards = widget.get_active() + + def wrapAroundChecked(self, widget): + """Signal handler for the "toggled" signal for the + wrapAroundCheckbox GtkCheckButton widget. The user has + [un]checked the "Wrap around" checkbox. + + Arguments: + - widget: the component that generated the signal. + """ + + self.windowWrap = widget.get_active() + + def closeButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the cancelButton + GtkButton widget. The user has clicked the Cancel button. + Hide the dialog. + + Arguments: + - widget: the component that generated the signal. + """ + + self.get_widget("findDialog").hide() + + def findButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the findButton + GtkButton widget. The user has clicked the Find button. + Call the method to begin the search. + + Arguments: + - widget: the component that generated the signal. + """ + + cthulhu_state.searchQuery = find.SearchQuery() + cthulhu_state.searchQuery.searchString = self.searchString + cthulhu_state.searchQuery.searchBackwards = self.searchBackwards + cthulhu_state.searchQuery.caseSensitive = self.caseSensitive + cthulhu_state.searchQuery.matchEntireWord = self.matchEntireWord + cthulhu_state.searchQuery.startAtTop = self.startAtTop + cthulhu_state.searchQuery.windowWrap = self.windowWrap + + self.activeScript.findCommandRun = True + + # Merely hiding the dialog causes the find to take place before + # the original window has fully regained focus. + self.get_widget("findDialog").destroy() + + + def findDialogDestroyed(self, widget): + """Signal handler for the "destroyed" signal for the findDialog + GtkWindow widget. Reset OS to None. + + Arguments: + - widget: the component that generated the signal. + """ + + global OS + + OS = None + +def showFindUI(): + global OS + + if not OS: + uiFile = os.path.join(cthulhu_platform.datadir, + cthulhu_platform.package, + "ui", + "cthulhu-find.ui") + OS = CthulhuFindGUI(uiFile, "findDialog") + OS.init() + + OS.showGUI() + +def main(): + locale.setlocale(locale.LC_ALL, '') + + showFindUI() + + Gtk.main() + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_navlist.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_navlist.py new file mode 100644 index 0000000..ffa00c6 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_navlist.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Displays a GUI for Cthulhu navigation list dialogs""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2012 Igalia, S.L." +__license__ = "LGPL" + +from gi.repository import GObject, Gdk, Gtk + +from . import debug +from . import guilabels +from . import cthulhu_state +from .ax_event_synthesizer import AXEventSynthesizer +from .ax_object import AXObject + +class CthulhuNavListGUI: + + def __init__(self, title, columnHeaders, rows, selectedRow): + self._tree = None + self._activateButton = None + self._jumpToButton = None + self._gui = self._createNavListDialog(columnHeaders, rows, selectedRow) + self._gui.set_title(title) + self._gui.set_modal(True) + self._gui.set_keep_above(True) + self._gui.set_focus_on_map(True) + self._gui.set_accept_focus(True) + self._script = cthulhu_state.activeScript + self._document = None + + def _createNavListDialog(self, columnHeaders, rows, selectedRow): + dialog = Gtk.Dialog() + dialog.set_default_size(500, 400) + + grid = Gtk.Grid() + contentArea = dialog.get_content_area() + contentArea.add(grid) + + scrolledWindow = Gtk.ScrolledWindow() + grid.add(scrolledWindow) + + self._tree = Gtk.TreeView() + self._tree.set_hexpand(True) + self._tree.set_vexpand(True) + scrolledWindow.add(self._tree) + + cols = [GObject.TYPE_OBJECT, GObject.TYPE_INT] + cols.extend(len(columnHeaders) * [GObject.TYPE_STRING]) + model = Gtk.ListStore(*cols) + + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn("Accessible", cell, text=0) + column.set_visible(False) + self._tree.append_column(column) + + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn("offset", cell, text=1) + column.set_visible(False) + self._tree.append_column(column) + + for i, header in enumerate(columnHeaders): + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(header, cell, text=i+2) + column.set_sort_column_id(i+2) + self._tree.append_column(column) + + for row in rows: + rowIter = model.append(None) + for i, cell in enumerate(row): + model.set_value(rowIter, i, cell) + + self._tree.set_model(model) + selection = self._tree.get_selection() + selection.select_path(selectedRow) + + btn = dialog.add_button(guilabels.BTN_CANCEL, Gtk.ResponseType.CANCEL) + btn.connect('clicked', self._onCancelClicked) + + self._jumpToButton = dialog.add_button(guilabels.BTN_JUMP_TO, Gtk.ResponseType.APPLY) + self._jumpToButton.connect('clicked', self._onJumpToClicked) + + self._activateButton = dialog.add_button( + guilabels.ACTIVATE, Gtk.ResponseType.OK) + self._activateButton.connect('clicked', self._onActivateClicked) + self._activateButton.grab_default() + + self._tree.connect('key-release-event', self._onKeyRelease) + self._tree.connect('cursor-changed', self._onCursorChanged) + self._tree.set_search_column(2) + + return dialog + + def showGUI(self): + self._document = self._script.utilities.documentFrame() + x, y, width, height = self._script.utilities.getBoundingBox(self._document) + if (width and height): + self._gui.move(x + 100, y + 100) + + self._gui.show_all() + ts = cthulhu_state.lastInputEvent.timestamp + if ts == 0: + ts = Gtk.get_current_event_time() + self._gui.present_with_time(ts) + + def _onCursorChanged(self, widget): + obj, offset = self._getSelectedAccessibleAndOffset() + n_actions = AXObject.get_n_actions(obj) + self._activateButton.set_sensitive(n_actions > 0) + if n_actions > 0: + self._activateButton.grab_default() + else: + self._jumpToButton.grab_default() + + def _onKeyRelease(self, widget, event): + keycode = event.hardware_keycode + keymap = Gdk.Keymap.get_default() + entries_for_keycode = keymap.get_entries_for_keycode(keycode) + entries = entries_for_keycode[-1] + eventString = Gdk.keyval_name(entries[0]) + if eventString == 'Return': + self._gui.activate_default() + + def _onCancelClicked(self, widget): + self._gui.destroy() + + def _onJumpToClicked(self, widget): + obj, offset = self._getSelectedAccessibleAndOffset() + self._gui.destroy() + self._script.utilities.setCaretPosition(obj, offset, self._document) + + def _onActivateClicked(self, widget): + obj, offset = self._getSelectedAccessibleAndOffset() + self._gui.destroy() + if not obj: + return + + self._script.utilities.setCaretPosition(obj, offset) + if not AXEventSynthesizer.try_all_clickable_actions(obj): + tokens = ["INFO: Attempting a synthesized click on", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + AXEventSynthesizer.click_object(obj) + + def _getSelectedAccessibleAndOffset(self): + if not self._tree: + msg = "ERROR: Could not get navlist tree" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None, -1 + + selection = self._tree.get_selection() + if not selection: + msg = "ERROR: Could not get selection for navlist tree" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None, -1 + + model, paths = selection.get_selected_rows() + if not paths: + msg = "ERROR: Could not get paths for navlist tree" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None, -1 + + obj = model.get_value(model.get_iter(paths[0]), 0) + offset = model.get_value(model.get_iter(paths[0]), 1) + return obj, max(0, offset) + +def showUI(title='', columnHeaders=[], rows=[()], selectedRow=0): + gui = CthulhuNavListGUI(title, columnHeaders, rows, selectedRow) + gui.showGUI() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_prefs.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_prefs.py new file mode 100644 index 0000000..0de0159 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_prefs.py @@ -0,0 +1,3841 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Displays a GUI for the user to set Cthulhu preferences.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import os +from gi.repository import Gdk +from gi.repository import GLib +from gi.repository import Gtk +from gi.repository import GObject +from gi.repository import Pango +import time + +from . import acss +from . import debug +from . import event_manager +from . import guilabels +from . import messages +from . import cthulhu +from . import cthulhu_gtkbuilder +from . import cthulhu_gui_profile +from . import cthulhu_state +from . import settings +from . import settings_manager +from . import input_event +from . import keybindings +from . import pronunciation_dict +from . import braille +from . import speech +from . import speechserver +from . import text_attribute_names +from .ax_object import AXObject + +_settingsManager = settings_manager.getManager() + +try: + import louis +except ImportError: + louis = None +from .cthulhu_platform import tablesdir +if louis and not tablesdir: + louis = None + +(HANDLER, DESCRIP, MOD_MASK1, MOD_USED1, KEY1, CLICK_COUNT1, OLDTEXT1, \ + TEXT1, MODIF, EDITABLE) = list(range(10)) + +(NAME, IS_SPOKEN, IS_BRAILLED, VALUE) = list(range(4)) + +(ACTUAL, REPLACEMENT) = list(range(2)) + +# Must match the order of voice types in the GtkBuilder file. +# +(DEFAULT, UPPERCASE, HYPERLINK, SYSTEM) = list(range(4)) + +# Must match the order that the timeFormatCombo is populated. +# +(TIME_FORMAT_LOCALE, TIME_FORMAT_12_HM, TIME_FORMAT_12_HMS, TIME_FORMAT_24_HMS, + TIME_FORMAT_24_HMS_WITH_WORDS, TIME_FORMAT_24_HM, + TIME_FORMAT_24_HM_WITH_WORDS) = list(range(7)) + +# Must match the order that the dateFormatCombo is populated. +# +(DATE_FORMAT_LOCALE, DATE_FORMAT_NUMBERS_DM, DATE_FORMAT_NUMBERS_MD, + DATE_FORMAT_NUMBERS_DMY, DATE_FORMAT_NUMBERS_MDY, DATE_FORMAT_NUMBERS_YMD, + DATE_FORMAT_FULL_DM, DATE_FORMAT_FULL_MD, DATE_FORMAT_FULL_DMY, + DATE_FORMAT_FULL_MDY, DATE_FORMAT_FULL_YMD, DATE_FORMAT_ABBREVIATED_DM, + DATE_FORMAT_ABBREVIATED_MD, DATE_FORMAT_ABBREVIATED_DMY, + DATE_FORMAT_ABBREVIATED_MDY, DATE_FORMAT_ABBREVIATED_YMD) = list(range(16)) + +class CthulhuSetupGUI(cthulhu_gtkbuilder.GtkBuilderWrapper): + + def __init__(self, fileName, windowName, prefsDict): + """Initialize the Cthulhu configuration GUI. + + Arguments: + - fileName: name of the GtkBuilder file. + - windowName: name of the component to get from the GtkBuilder file. + - prefsDict: dictionary of preferences to use during initialization + """ + + cthulhu_gtkbuilder.GtkBuilderWrapper.__init__(self, fileName, windowName) + self.prefsDict = prefsDict + + self._defaultProfile = ['Default', 'default'] + self.bbindings = None + self.cellRendererText = None + self.defaultVoice = None + self.disableKeyGrabPref = None + self.getTextAttributesView = None + self.hyperlinkVoice = None + self.initializingSpeech = None + self.kbindings = None + self.keyBindingsModel = None + self.keyBindView = None + self.newBinding = None + self.pendingKeyBindings = None + self.planeCellRendererText = None + self.pronunciationModel = None + self.pronunciationView = None + self.screenHeight = None + self.screenWidth = None + self.speechFamiliesChoice = None + self.speechFamiliesChoices = None + self.speechFamiliesModel = None + self.speechLanguagesChoice = None + self.speechLanguagesChoices = None + self.speechLanguagesModel = None + self.speechFamilies = [] + self.speechServersChoice = None + self.speechServersChoices = None + self.speechServersModel = None + self.speechSystemsChoice = None + self.speechSystemsChoices = None + self.speechSystemsModel = None + self.systemVoice = None + self.uppercaseVoice = None + self.window = None + self.workingFactories = None + self.savedGain = None + self.savedPitch = None + self.savedRate = None + self._isInitialSetup = False + self.selectedFamilyChoices = {} + self.selectedLanguageChoices = {} + self.profilesCombo = None + self.profilesComboModel = None + self.startingProfileCombo = None + self._capturedKey = [] + self.script = None + + def init(self, script): + """Initialize the Cthulhu configuration GUI. Read the users current + set of preferences and set the GUI state to match. Setup speech + support and populate the combo box lists on the Speech Tab pane + accordingly. + """ + + self.script = script + + # Restore the default rate/pitch/gain, + # in case the user played with the sliders. + # + try: + voices = _settingsManager.getSetting('voices') + defaultVoice = voices[settings.DEFAULT_VOICE] + except KeyError: + defaultVoice = {} + try: + self.savedGain = defaultVoice[acss.ACSS.GAIN] + except KeyError: + self.savedGain = 10.0 + try: + self.savedPitch = defaultVoice[acss.ACSS.AVERAGE_PITCH] + except KeyError: + self.savedPitch = 5.0 + try: + self.savedRate = defaultVoice[acss.ACSS.RATE] + except KeyError: + self.savedRate = 50.0 + + # ***** Key Bindings treeview initialization ***** + + self.keyBindView = self.get_widget("keyBindingsTreeview") + + if self.keyBindView.get_columns(): + for column in self.keyBindView.get_columns(): + self.keyBindView.remove_column(column) + + self.keyBindingsModel = Gtk.TreeStore( + GObject.TYPE_STRING, # Handler name + GObject.TYPE_STRING, # Human Readable Description + GObject.TYPE_STRING, # Modifier mask 1 + GObject.TYPE_STRING, # Used Modifiers 1 + GObject.TYPE_STRING, # Modifier key name 1 + GObject.TYPE_STRING, # Click count 1 + GObject.TYPE_STRING, # Original Text of the Key Binding Shown 1 + GObject.TYPE_STRING, # Text of the Key Binding Shown 1 + GObject.TYPE_BOOLEAN, # Key Modified by User + GObject.TYPE_BOOLEAN) # Row with fields editable or not + + self.planeCellRendererText = Gtk.CellRendererText() + + self.cellRendererText = Gtk.CellRendererText() + self.cellRendererText.set_property("ellipsize", Pango.EllipsizeMode.END) + + # HANDLER - invisble column + # + column = Gtk.TreeViewColumn("Handler", + self.planeCellRendererText, + text=HANDLER) + column.set_resizable(True) + column.set_visible(False) + column.set_sort_column_id(HANDLER) + self.keyBindView.append_column(column) + + # DESCRIP + # + column = Gtk.TreeViewColumn(guilabels.KB_HEADER_FUNCTION, + self.cellRendererText, + text=DESCRIP) + column.set_resizable(True) + column.set_min_width(380) + column.set_sort_column_id(DESCRIP) + self.keyBindView.append_column(column) + + # MOD_MASK1 - invisble column + # + column = Gtk.TreeViewColumn("Mod.Mask 1", + self.planeCellRendererText, + text=MOD_MASK1) + column.set_visible(False) + column.set_resizable(True) + column.set_sort_column_id(MOD_MASK1) + self.keyBindView.append_column(column) + + # MOD_USED1 - invisble column + # + column = Gtk.TreeViewColumn("Use Mod.1", + self.planeCellRendererText, + text=MOD_USED1) + column.set_visible(False) + column.set_resizable(True) + column.set_sort_column_id(MOD_USED1) + self.keyBindView.append_column(column) + + # KEY1 - invisble column + # + column = Gtk.TreeViewColumn("Key1", + self.planeCellRendererText, + text=KEY1) + column.set_resizable(True) + column.set_visible(False) + column.set_sort_column_id(KEY1) + self.keyBindView.append_column(column) + + # CLICK_COUNT1 - invisble column + # + column = Gtk.TreeViewColumn("ClickCount1", + self.planeCellRendererText, + text=CLICK_COUNT1) + column.set_resizable(True) + column.set_visible(False) + column.set_sort_column_id(CLICK_COUNT1) + self.keyBindView.append_column(column) + + # OLDTEXT1 - invisble column which will store a copy of the + # original keybinding in TEXT1 prior to the Apply or OK + # buttons being pressed. This will prevent automatic + # resorting each time a cell is edited. + # + column = Gtk.TreeViewColumn("OldText1", + self.planeCellRendererText, + text=OLDTEXT1) + column.set_resizable(True) + column.set_visible(False) + column.set_sort_column_id(OLDTEXT1) + self.keyBindView.append_column(column) + + # TEXT1 + # + rendererText = Gtk.CellRendererText() + rendererText.connect("editing-started", + self.editingKey, + self.keyBindingsModel) + rendererText.connect("editing-canceled", + self.editingCanceledKey) + rendererText.connect('edited', + self.editedKey, + self.keyBindingsModel, + MOD_MASK1, MOD_USED1, KEY1, CLICK_COUNT1, TEXT1) + + column = Gtk.TreeViewColumn(guilabels.KB_HEADER_KEY_BINDING, + rendererText, + text=TEXT1, + editable=EDITABLE) + + column.set_resizable(True) + column.set_sort_column_id(OLDTEXT1) + self.keyBindView.append_column(column) + + # MODIF + # + rendererToggle = Gtk.CellRendererToggle() + rendererToggle.connect('toggled', + self.keyModifiedToggle, + self.keyBindingsModel, + MODIF) + column = Gtk.TreeViewColumn(guilabels.KB_MODIFIED, + rendererToggle, + active=MODIF, + activatable=EDITABLE) + #column.set_visible(False) + column.set_resizable(True) + column.set_sort_column_id(MODIF) + self.keyBindView.append_column(column) + + # EDITABLE - invisble column + # + rendererToggle = Gtk.CellRendererToggle() + rendererToggle.set_property('activatable', False) + column = Gtk.TreeViewColumn("Modified", + rendererToggle, + active=EDITABLE) + column.set_visible(False) + column.set_resizable(True) + column.set_sort_column_id(EDITABLE) + self.keyBindView.append_column(column) + + # Populates the treeview with all the keybindings: + # + self._populateKeyBindings() + + self.window = self.get_widget("cthulhuSetupWindow") + + self._setKeyEchoItems() + + self.speechSystemsModel = \ + self._initComboBox(self.get_widget("speechSystems")) + self.speechServersModel = \ + self._initComboBox(self.get_widget("speechServers")) + self.speechLanguagesModel = \ + self._initComboBox(self.get_widget("speechLanguages")) + self.speechFamiliesModel = \ + self._initComboBox(self.get_widget("speechFamilies")) + self._initSpeechState() + + # TODO - JD: Will this ever be the case?? + self._isInitialSetup = \ + not os.path.exists(_settingsManager.getPrefsDir()) + + appPage = self.script.getAppPreferencesGUI() + if appPage: + label = Gtk.Label(label=AXObject.get_name(self.script.app)) + self.get_widget("notebook").append_page(appPage, label) + + self._initGUIState() + + def _getACSSForVoiceType(self, voiceType): + """Return the ACSS value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + + Returns the voice dictionary for the given voice type. + """ + + if voiceType == DEFAULT: + voiceACSS = self.defaultVoice + elif voiceType == UPPERCASE: + voiceACSS = self.uppercaseVoice + elif voiceType == HYPERLINK: + voiceACSS = self.hyperlinkVoice + elif voiceType == SYSTEM: + voiceACSS = self.systemVoice + else: + voiceACSS = self.defaultVoice + + return voiceACSS + + def writeUserPreferences(self): + """Write out the user's generic Cthulhu preferences. + """ + pronunciationDict = self.getModelDict(self.pronunciationModel) + keyBindingsDict = self.getKeyBindingsModelDict(self.keyBindingsModel) + self.prefsDict.update(self.script.getPreferencesFromGUI()) + _settingsManager.saveSettings(self.script, + self.prefsDict, + pronunciationDict, + keyBindingsDict) + + def _getKeyValueForVoiceType(self, voiceType, key, useDefault=True): + """Look for the value of the given key in the voice dictionary + for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + - key: the key to look for in the voice dictionary. + - useDefault: if True, and the key isn't found for the given voice + type, the look for it in the default voice dictionary + as well. + + Returns the value of the given key, or None if it's not set. + """ + + if voiceType == DEFAULT: + voice = self.defaultVoice + elif voiceType == UPPERCASE: + voice = self.uppercaseVoice + if key not in voice: + if not useDefault: + return None + voice = self.defaultVoice + elif voiceType == HYPERLINK: + voice = self.hyperlinkVoice + if key not in voice: + if not useDefault: + return None + voice = self.defaultVoice + elif voiceType == SYSTEM: + voice = self.systemVoice + if key not in voice: + if not useDefault: + return None + voice = self.defaultVoice + else: + voice = self.defaultVoice + + if key in voice: + return voice[key] + else: + return None + + def _getFamilyNameForVoiceType(self, voiceType): + """Gets the name of the voice family for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + + Returns the name of the voice family for the given voice type, + or None if not set. + """ + + familyName = None + family = self._getKeyValueForVoiceType(voiceType, acss.ACSS.FAMILY) + + if family and speechserver.VoiceFamily.NAME in family: + familyName = family[speechserver.VoiceFamily.NAME] + + return familyName + + def _setFamilyNameForVoiceType(self, voiceType, name, language, dialect, variant): + """Sets the name of the voice family for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + - name: the name of the voice family to set. + - language: the locale of the voice family to set. + - dialect: the dialect of the voice family to set. + """ + + family = self._getKeyValueForVoiceType(voiceType, + acss.ACSS.FAMILY, + False) + + voiceACSS = self._getACSSForVoiceType(voiceType) + if family: + family[speechserver.VoiceFamily.NAME] = name + family[speechserver.VoiceFamily.LANG] = language + family[speechserver.VoiceFamily.DIALECT] = dialect + family[speechserver.VoiceFamily.VARIANT] = variant + else: + voiceACSS[acss.ACSS.FAMILY] = {} + voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.NAME] = name + voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.LANG] = language + voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.DIALECT] = dialect + voiceACSS[acss.ACSS.FAMILY][speechserver.VoiceFamily.VARIANT] = variant + voiceACSS['established'] = True + + #settings.voices[voiceType] = voiceACSS + + def _getRateForVoiceType(self, voiceType): + """Gets the speaking rate value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + + Returns the rate value for the given voice type, or None if + not set. + """ + + return self._getKeyValueForVoiceType(voiceType, acss.ACSS.RATE) + + def _setRateForVoiceType(self, voiceType, value): + """Sets the speaking rate value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + - value: the rate value to set. + """ + + voiceACSS = self._getACSSForVoiceType(voiceType) + voiceACSS[acss.ACSS.RATE] = value + voiceACSS['established'] = True + #settings.voices[voiceType] = voiceACSS + + def _getPitchForVoiceType(self, voiceType): + """Gets the pitch value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + + Returns the pitch value for the given voice type, or None if + not set. + """ + + return self._getKeyValueForVoiceType(voiceType, + acss.ACSS.AVERAGE_PITCH) + + def _setPitchForVoiceType(self, voiceType, value): + """Sets the pitch value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + - value: the pitch value to set. + """ + + voiceACSS = self._getACSSForVoiceType(voiceType) + voiceACSS[acss.ACSS.AVERAGE_PITCH] = value + voiceACSS['established'] = True + #settings.voices[voiceType] = voiceACSS + + def _getVolumeForVoiceType(self, voiceType): + """Gets the volume (gain) value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + + Returns the volume (gain) value for the given voice type, or + None if not set. + """ + + return self._getKeyValueForVoiceType(voiceType, acss.ACSS.GAIN) + + def _setVolumeForVoiceType(self, voiceType, value): + """Sets the volume (gain) value for the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + - value: the volume (gain) value to set. + """ + + voiceACSS = self._getACSSForVoiceType(voiceType) + voiceACSS[acss.ACSS.GAIN] = value + voiceACSS['established'] = True + #settings.voices[voiceType] = voiceACSS + + def _setVoiceSettingsForVoiceType(self, voiceType): + """Sets the family, rate, pitch and volume GUI components based + on the given voice type. + + Arguments: + - voiceType: one of DEFAULT, UPPERCASE, HYPERLINK, SYSTEM + """ + + familyName = self._getFamilyNameForVoiceType(voiceType) + self._setSpeechFamiliesChoice(familyName) + + rate = self._getRateForVoiceType(voiceType) + if rate is not None: + self.get_widget("rateScale").set_value(rate) + else: + self.get_widget("rateScale").set_value(50.0) + + pitch = self._getPitchForVoiceType(voiceType) + if pitch is not None: + self.get_widget("pitchScale").set_value(pitch) + else: + self.get_widget("pitchScale").set_value(5.0) + + volume = self._getVolumeForVoiceType(voiceType) + if volume is not None: + self.get_widget("volumeScale").set_value(volume) + else: + self.get_widget("volumeScale").set_value(10.0) + + def _setSpeechFamiliesChoice(self, familyName): + """Sets the active item in the families ("Person:") combo box + to the given family name. + + Arguments: + - familyName: the family name to use to set the active combo box item. + """ + + if len(self.speechFamilies) == 0: + return + + languageSet = False + familySet = False + for family in self.speechFamilies: + name = family[speechserver.VoiceFamily.NAME] + if name == familyName: + lang = family[speechserver.VoiceFamily.LANG] + dialect = family[speechserver.VoiceFamily.DIALECT] + + if dialect: + language = lang + '-' + dialect + else: + language = lang + + i = 0 + for languageChoice in self.speechLanguagesChoices: + if languageChoice == language: + self.get_widget("speechLanguages").set_active(i) + self.speechLanguagesChoice = self.speechLanguagesChoices[i] + languageSet = True + + self._setupFamilies() + + i = 0 + for familyChoice in self.speechFamiliesChoices: + name = familyChoice[speechserver.VoiceFamily.NAME] + if name == familyName: + self.get_widget("speechFamilies").set_active(i) + self.speechFamiliesChoice = self.speechFamiliesChoices[i] + familySet = True + break + i += 1 + + break + + i += 1 + + break + + if not languageSet: + tokens = ["PREFERENCES DIALOG: Could not find speech language match for", familyName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.get_widget("speechLanguages").set_active(0) + self.speechLanguagesChoice = self.speechLanguagesChoices[0] + + if languageSet: + self.selectedLanguageChoices[self.speechServersChoice] = i + + if not familySet: + tokens = ["PREFERENCES DIALOG: Could not find speech family match for", familyName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.get_widget("speechFamilies").set_active(0) + self.speechFamiliesChoice = self.speechFamiliesChoices[0] + + if familySet: + self.selectedFamilyChoices[self.speechServersChoice, + self.speechLanguagesChoice] = i + + def _setupFamilies(self): + """Gets the list of voice variants for the current speech server and + current language. + If there are variants, get the information associated with + each voice variant and add an entry for it to the variants + GtkComboBox list. + """ + + combobox = self.get_widget("speechFamilies") + combobox.set_model(None) + self.speechFamiliesModel.clear() + + currentLanguage = self.speechLanguagesChoice + + i = 0 + self.speechFamiliesChoices = [] + for family in self.speechFamilies: + lang = family[speechserver.VoiceFamily.LANG] + dialect = family[speechserver.VoiceFamily.DIALECT] + + if dialect: + language = lang + '-' + dialect + else: + language = lang + + if language != currentLanguage: + continue + + name = family[speechserver.VoiceFamily.NAME] + self.speechFamiliesChoices.append(family) + self.speechFamiliesModel.append((i, name)) + i += 1 + + combobox.set_model(self.speechFamiliesModel) + if i == 0: + tokens = ["No speech family was available for", str(currentLanguage), "."] + debug.printTokens(debug.LEVEL_SEVERE, tokens, True) + debug.printStack(debug.LEVEL_FINEST) + self.speechFamiliesChoice = None + return + + # If user manually selected a family for the current speech server + # this choice it's restored. In other case the first family + # (usually the default one) is selected + # + selectedIndex = 0 + if (self.speechServersChoice, self.speechLanguagesChoice) \ + in self.selectedFamilyChoices: + selectedIndex = self.selectedFamilyChoices[self.speechServersChoice, + self.speechLanguagesChoice] + + self.get_widget("speechFamilies").set_active(selectedIndex) + + def _setSpeechLanguagesChoice(self, languageName): + """Sets the active item in the languages ("Language:") combo box + to the given language name. + + Arguments: + - languageName: the language name to use to set the active combo box item. + """ + + if len(self.speechLanguagesChoices) == 0: + return + + valueSet = False + i = 0 + for language in self.speechLanguagesChoices: + if language == languageName: + self.get_widget("speechLanguages").set_active(i) + self.speechLanguagesChoice = self.speechLanguagesChoices[i] + valueSet = True + break + i += 1 + + if not valueSet: + tokens = ["PREFERENCES DIALOG: Could not find speech language match for", languageName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.get_widget("speechLanguages").set_active(0) + self.speechLanguagesChoice = self.speechLanguagesChoices[0] + + if valueSet: + self.selectedLanguageChoices[self.speechServersChoice] = i + + self._setupFamilies() + + def _setupVoices(self): + """Gets the list of voices for the current speech server. + If there are families, get the information associated with + each voice family and add an entry for it to the families + GtkComboBox list. + """ + + combobox = self.get_widget("speechLanguages") + combobox.set_model(None) + self.speechLanguagesModel.clear() + self.speechFamilies = self.speechServersChoice.getVoiceFamilies() + self.speechLanguagesChoices = [] + + if len(self.speechFamilies) == 0: + debug.printMessage(debug.LEVEL_SEVERE, "No speech voice was available.") + debug.printStack(debug.LEVEL_FINEST) + self.speechLanguagesChoice = None + return + + done = {} + i = 0 + for family in self.speechFamilies: + lang = family[speechserver.VoiceFamily.LANG] + dialect = family[speechserver.VoiceFamily.DIALECT] + if (lang,dialect) in done: + continue + done[lang,dialect] = True + + if dialect: + language = lang + '-' + dialect + else: + language = lang + + # TODO: get translated language name from CLDR or such + msg = language + if msg == "": + # Unsupported locale + msg = "default language" + + self.speechLanguagesChoices.append(language) + self.speechLanguagesModel.append((i, msg)) + i += 1 + + # If user manually selected a language for the current speech server + # this choice it's restored. In other case the first language + # (usually the default one) is selected + # + selectedIndex = 0 + if self.speechServersChoice in self.selectedLanguageChoices: + selectedIndex = self.selectedLanguageChoices[self.speechServersChoice] + + combobox.set_model(self.speechLanguagesModel) + + self.get_widget("speechLanguages").set_active(selectedIndex) + if self.initializingSpeech: + self.speechLanguagesChoice = self.speechLanguagesChoices[selectedIndex] + + self._setupFamilies() + + # The family name will be selected as part of selecting the + # voice type. Whenever the families change, we'll reset the + # voice type selection to the first one ("Default"). + # + comboBox = self.get_widget("voiceTypesCombo") + types = [guilabels.SPEECH_VOICE_TYPE_DEFAULT, + guilabels.SPEECH_VOICE_TYPE_UPPERCASE, + guilabels.SPEECH_VOICE_TYPE_HYPERLINK, + guilabels.SPEECH_VOICE_TYPE_SYSTEM] + self.populateComboBox(comboBox, types) + comboBox.set_active(DEFAULT) + voiceType = comboBox.get_active() + self._setVoiceSettingsForVoiceType(voiceType) + + def _setSpeechServersChoice(self, serverInfo): + """Sets the active item in the speech servers combo box to the + given server. + + Arguments: + - serversChoices: the list of available speech servers. + - serverInfo: the speech server to use to set the active combo + box item. + """ + + if len(self.speechServersChoices) == 0: + return + + # We'll fallback to whatever we happen to be using in the event + # that this preference has never been set. + # + if not serverInfo: + serverInfo = speech.getInfo() + + valueSet = False + i = 0 + for server in self.speechServersChoices: + if serverInfo == server.getInfo(): + self.get_widget("speechServers").set_active(i) + self.speechServersChoice = server + valueSet = True + break + i += 1 + + if not valueSet: + tokens = ["PREFERENCES DIALOG: Could not find speech server match for", serverInfo] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.get_widget("speechServers").set_active(0) + self.speechServersChoice = self.speechServersChoices[0] + + self._setupVoices() + + def _setupSpeechServers(self): + """Gets the list of speech servers for the current speech factory. + If there are servers, get the information associated with each + speech server and add an entry for it to the speechServers + GtkComboBox list. Set the current choice to be the first item. + """ + + combobox = self.get_widget("speechServers") + combobox.set_model(None) + self.speechServersModel.clear() + self.speechServersChoices = \ + self.speechSystemsChoice.SpeechServer.getSpeechServers() + if len(self.speechServersChoices) == 0: + debug.printMessage(debug.LEVEL_SEVERE, "Speech not available.") + debug.printStack(debug.LEVEL_FINEST) + self.speechServersChoice = None + self.speechLanguagesChoices = [] + self.speechLanguagesChoice = None + self.speechFamiliesChoices = [] + self.speechFamiliesChoice = None + combobox.set_model(self.speechServersModel) + return + + i = 0 + for server in self.speechServersChoices: + name = server.getInfo()[0] + self.speechServersModel.append((i, name)) + i += 1 + + combobox.set_model(self.speechServersModel) + self._setSpeechServersChoice(self.prefsDict["speechServerInfo"]) + + def _setSpeechSystemsChoice(self, systemName): + """Set the active item in the speech systems combo box to the + given system name. + + Arguments: + - factoryChoices: the list of available speech factories (systems). + - systemName: the speech system name to use to set the active combo + box item. + """ + + systemName = systemName.strip("'") + + if len(self.speechSystemsChoices) == 0: + self.speechSystemsChoice = None + return + + valueSet = False + i = 0 + for speechSystem in self.speechSystemsChoices: + name = speechSystem.__name__ + if name.endswith(systemName): + self.get_widget("speechSystems").set_active(i) + self.speechSystemsChoice = self.speechSystemsChoices[i] + valueSet = True + break + i += 1 + + if not valueSet: + tokens = ["PREFERENCES DIALOG: Could not find speech system match for", systemName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.get_widget("speechSystems").set_active(0) + self.speechSystemsChoice = self.speechSystemsChoices[0] + + self._setupSpeechServers() + + def _setupSpeechSystems(self, factories): + """Sets up the speech systems combo box and sets the selection + to the preferred speech system. + + Arguments: + -factories: the list of known speech factories (working or not) + """ + + combobox = self.get_widget("speechSystems") + combobox.set_model(None) + self.speechSystemsModel.clear() + self.workingFactories = [] + for factory in factories: + try: + servers = factory.SpeechServer.getSpeechServers() + if len(servers): + self.workingFactories.append(factory) + except Exception: + debug.printException(debug.LEVEL_FINEST) + + self.speechSystemsChoices = [] + if len(self.workingFactories) == 0: + debug.printMessage(debug.LEVEL_SEVERE, "Speech not available.") + debug.printStack(debug.LEVEL_FINEST) + self.speechSystemsChoice = None + self.speechServersChoices = [] + self.speechServersChoice = None + self.speechLanguagesChoices = [] + self.speechLanguagesChoice = None + self.speechFamiliesChoices = [] + self.speechFamiliesChoice = None + combobox.set_model(self.speechSystemsModel) + return + + i = 0 + for workingFactory in self.workingFactories: + self.speechSystemsChoices.append(workingFactory) + name = workingFactory.SpeechServer.getFactoryName() + self.speechSystemsModel.append((i, name)) + i += 1 + + combobox.set_model(self.speechSystemsModel) + if self.prefsDict["speechServerFactory"]: + self._setSpeechSystemsChoice(self.prefsDict["speechServerFactory"]) + else: + self.speechSystemsChoice = None + + def _initSpeechState(self): + """Initialize the various speech components. + """ + + voices = self.prefsDict["voices"] + self.defaultVoice = acss.ACSS(voices.get(settings.DEFAULT_VOICE)) + self.uppercaseVoice = acss.ACSS(voices.get(settings.UPPERCASE_VOICE)) + self.hyperlinkVoice = acss.ACSS(voices.get(settings.HYPERLINK_VOICE)) + self.systemVoice = acss.ACSS(voices.get(settings.SYSTEM_VOICE)) + + # Just a note on general naming pattern: + # + # * = The name of the combobox + # *Model = the name of the comobox model + # *Choices = the Cthulhu/speech python objects + # *Choice = a value from *Choices + # + # Where * = speechSystems, speechServers, speechLanguages, speechFamilies + # + factories = _settingsManager.getSpeechServerFactories() + if len(factories) == 0 or not self.prefsDict.get('enableSpeech', True): + self.workingFactories = [] + self.speechSystemsChoice = None + self.speechServersChoices = [] + self.speechServersChoice = None + self.speechLanguagesChoices = [] + self.speechLanguagesChoice = None + self.speechFamiliesChoices = [] + self.speechFamiliesChoice = None + return + + try: + speech.init() + except Exception: + self.workingFactories = [] + self.speechSystemsChoice = None + self.speechServersChoices = [] + self.speechServersChoice = None + self.speechLanguagesChoices = [] + self.speechLanguagesChoice = None + self.speechFamiliesChoices = [] + self.speechFamiliesChoice = None + return + + # This cascades into systems->servers->voice_type->families... + # + self.initializingSpeech = True + self._setupSpeechSystems(factories) + self.initializingSpeech = False + + def _setSpokenTextAttributes(self, view, setAttributes, + state, moveToTop=False): + """Given a set of spoken text attributes, update the model used by the + text attribute tree view. + + Arguments: + - view: the text attribute tree view. + - setAttributes: the list of spoken text attributes to update. + - state: the state (True or False) that they all should be set to. + - moveToTop: if True, move these attributes to the top of the list. + """ + + model = view.get_model() + view.set_model(None) + + [attrList, attrDict] = \ + self.script.utilities.stringToKeysAndDict(setAttributes) + [allAttrList, allAttrDict] = self.script.utilities.stringToKeysAndDict( + _settingsManager.getSetting('allTextAttributes')) + + for i in range(0, len(attrList)): + for path in range(0, len(allAttrList)): + localizedKey = text_attribute_names.getTextAttributeName( + attrList[i], self.script) + localizedValue = text_attribute_names.getTextAttributeName( + attrDict[attrList[i]], self.script) + if localizedKey == model[path][NAME]: + thisIter = model.get_iter(path) + model.set_value(thisIter, NAME, localizedKey) + model.set_value(thisIter, IS_SPOKEN, state) + model.set_value(thisIter, VALUE, localizedValue) + if moveToTop: + thisIter = model.get_iter(path) + otherIter = model.get_iter(i) + model.move_before(thisIter, otherIter) + break + + view.set_model(model) + + def _setBrailledTextAttributes(self, view, setAttributes, state): + """Given a set of brailled text attributes, update the model used + by the text attribute tree view. + + Arguments: + - view: the text attribute tree view. + - setAttributes: the list of brailled text attributes to update. + - state: the state (True or False) that they all should be set to. + """ + + model = view.get_model() + view.set_model(None) + + [attrList, attrDict] = \ + self.script.utilities.stringToKeysAndDict(setAttributes) + [allAttrList, allAttrDict] = self.script.utilities.stringToKeysAndDict( + _settingsManager.getSetting('allTextAttributes')) + + for i in range(0, len(attrList)): + for path in range(0, len(allAttrList)): + localizedKey = text_attribute_names.getTextAttributeName( + attrList[i], self.script) + if localizedKey == model[path][NAME]: + thisIter = model.get_iter(path) + model.set_value(thisIter, IS_BRAILLED, state) + break + + view.set_model(model) + + def _getAppNameForAttribute(self, attributeName): + """Converts the given Atk attribute name into the application's + equivalent. This is necessary because an application or toolkit + (e.g. Gecko) might invent entirely new names for the same text + attributes. + + Arguments: + - attribName: The name of the text attribute + + Returns the application's equivalent name if found or attribName + otherwise. + """ + + return self.script.utilities.getAppNameForAttribute(attributeName) + + def _updateTextDictEntry(self): + """The user has updated the text attribute list in some way. Update + the "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" + preference strings to reflect the current state of the corresponding + text attribute lists. + """ + + model = self.getTextAttributesView.get_model() + spokenAttrStr = "" + brailledAttrStr = "" + noRows = model.iter_n_children(None) + for path in range(0, noRows): + localizedKey = model[path][NAME] + key = text_attribute_names.getTextAttributeKey(localizedKey) + + # Convert the normalized, Atk attribute name back into what + # the app/toolkit uses. + # + key = self._getAppNameForAttribute(key) + + localizedValue = model[path][VALUE] + value = text_attribute_names.getTextAttributeKey(localizedValue) + + if model[path][IS_SPOKEN]: + spokenAttrStr += key + ":" + value + "; " + if model[path][IS_BRAILLED]: + brailledAttrStr += key + ":" + value + "; " + + self.prefsDict["enabledSpokenTextAttributes"] = spokenAttrStr + self.prefsDict["enabledBrailledTextAttributes"] = brailledAttrStr + + def contractedBrailleToggled(self, checkbox): + grid = self.get_widget('contractionTableGrid') + grid.set_sensitive(checkbox.get_active()) + self.prefsDict["enableContractedBraille"] = checkbox.get_active() + + def contractionTableComboChanged(self, combobox): + model = combobox.get_model() + myIter = combobox.get_active_iter() + self.prefsDict["brailleContractionTable"] = model[myIter][1] + + def flashPersistenceToggled(self, checkbox): + grid = self.get_widget('flashMessageDurationGrid') + grid.set_sensitive(not checkbox.get_active()) + self.prefsDict["flashIsPersistent"] = checkbox.get_active() + + def textAttributeSpokenToggled(self, cell, path, model): + """The user has toggled the state of one of the text attribute + checkboxes to be spoken. Update our model to reflect this, then + update the "enabledSpokenTextAttributes" preference string. + + Arguments: + - cell: the cell that changed. + - path: the path of that cell. + - model: the model that the cell is part of. + """ + + thisIter = model.get_iter(path) + model.set(thisIter, IS_SPOKEN, not model[path][IS_SPOKEN]) + self._updateTextDictEntry() + + def textAttributeBrailledToggled(self, cell, path, model): + """The user has toggled the state of one of the text attribute + checkboxes to be brailled. Update our model to reflect this, + then update the "enabledBrailledTextAttributes" preference string. + + Arguments: + - cell: the cell that changed. + - path: the path of that cell. + - model: the model that the cell is part of. + """ + + thisIter = model.get_iter(path) + model.set(thisIter, IS_BRAILLED, not model[path][IS_BRAILLED]) + self._updateTextDictEntry() + + def textAttrValueEdited(self, cell, path, new_text, model): + """The user has edited the value of one of the text attributes. + Update our model to reflect this, then update the + "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" + preference strings. + + Arguments: + - cell: the cell that changed. + - path: the path of that cell. + - new_text: the new text attribute value string. + - model: the model that the cell is part of. + """ + + thisIter = model.get_iter(path) + model.set(thisIter, VALUE, new_text) + self._updateTextDictEntry() + + def textAttrCursorChanged(self, widget): + """Set the search column in the text attribute tree view + depending upon which column the user currently has the cursor in. + """ + + [path, focusColumn] = self.getTextAttributesView.get_cursor() + if focusColumn: + noColumns = len(self.getTextAttributesView.get_columns()) + for i in range(0, noColumns): + col = self.getTextAttributesView.get_column(i) + if focusColumn == col: + self.getTextAttributesView.set_search_column(i) + break + + def _createTextAttributesTreeView(self): + """Create the text attributes tree view. The view is the + textAttributesTreeView GtkTreeView widget. The view will consist + of a list containing three columns: + IS_SPOKEN - a checkbox whose state indicates whether this text + attribute will be spoken or not. + NAME - the text attribute name. + VALUE - if set, (and this attributes is enabled for speaking), + then this attribute will be spoken unless it equals + this value. + """ + + self.getTextAttributesView = self.get_widget("textAttributesTreeView") + + if self.getTextAttributesView.get_columns(): + for column in self.getTextAttributesView.get_columns(): + self.getTextAttributesView.remove_column(column) + + model = Gtk.ListStore(GObject.TYPE_STRING, + GObject.TYPE_BOOLEAN, + GObject.TYPE_BOOLEAN, + GObject.TYPE_STRING) + + # Initially setup the list store model based on the values of all + # the known text attributes. + # + [allAttrList, allAttrDict] = self.script.utilities.stringToKeysAndDict( + _settingsManager.getSetting('allTextAttributes')) + for i in range(0, len(allAttrList)): + thisIter = model.append() + localizedKey = text_attribute_names.getTextAttributeName( + allAttrList[i], self.script) + localizedValue = text_attribute_names.getTextAttributeName( + allAttrDict[allAttrList[i]], self.script) + model.set_value(thisIter, NAME, localizedKey) + model.set_value(thisIter, IS_SPOKEN, False) + model.set_value(thisIter, IS_BRAILLED, False) + model.set_value(thisIter, VALUE, localizedValue) + + self.getTextAttributesView.set_model(model) + + # Attribute Name column (NAME). + column = Gtk.TreeViewColumn(guilabels.TEXT_ATTRIBUTE_NAME) + column.set_min_width(250) + column.set_resizable(True) + renderer = Gtk.CellRendererText() + column.pack_end(renderer, True) + column.add_attribute(renderer, 'text', NAME) + self.getTextAttributesView.insert_column(column, 0) + + # Attribute Speak column (IS_SPOKEN). + speakAttrColumnLabel = guilabels.PRESENTATION_SPEAK + column = Gtk.TreeViewColumn(speakAttrColumnLabel) + renderer = Gtk.CellRendererToggle() + column.pack_start(renderer, False) + column.add_attribute(renderer, 'active', IS_SPOKEN) + renderer.connect("toggled", + self.textAttributeSpokenToggled, + model) + self.getTextAttributesView.insert_column(column, 1) + column.clicked() + + # Attribute Mark in Braille column (IS_BRAILLED). + markAttrColumnLabel = guilabels.PRESENTATION_MARK_IN_BRAILLE + column = Gtk.TreeViewColumn(markAttrColumnLabel) + renderer = Gtk.CellRendererToggle() + column.pack_start(renderer, False) + column.add_attribute(renderer, 'active', IS_BRAILLED) + renderer.connect("toggled", + self.textAttributeBrailledToggled, + model) + self.getTextAttributesView.insert_column(column, 2) + column.clicked() + + # Attribute Value column (VALUE) + column = Gtk.TreeViewColumn(guilabels.PRESENTATION_PRESENT_UNLESS) + renderer = Gtk.CellRendererText() + renderer.set_property('editable', True) + column.pack_end(renderer, True) + column.add_attribute(renderer, 'text', VALUE) + renderer.connect("edited", self.textAttrValueEdited, model) + + self.getTextAttributesView.insert_column(column, 4) + + # Check all the enabled (spoken) text attributes. + # + self._setSpokenTextAttributes( + self.getTextAttributesView, + _settingsManager.getSetting('enabledSpokenTextAttributes'), + True, True) + + # Check all the enabled (brailled) text attributes. + # + self._setBrailledTextAttributes( + self.getTextAttributesView, + _settingsManager.getSetting('enabledBrailledTextAttributes'), + True) + + # Connect a handler for when the user changes columns within the + # view, so that we can adjust the search column for item lookups. + # + self.getTextAttributesView.connect("cursor_changed", + self.textAttrCursorChanged) + + def pronActualValueEdited(self, cell, path, new_text, model): + """The user has edited the value of one of the actual strings in + the pronunciation dictionary. Update our model to reflect this. + + Arguments: + - cell: the cell that changed. + - path: the path of that cell. + - new_text: the new pronunciation dictionary actual string. + - model: the model that the cell is part of. + """ + + thisIter = model.get_iter(path) + model.set(thisIter, ACTUAL, new_text) + + def pronReplacementValueEdited(self, cell, path, new_text, model): + """The user has edited the value of one of the replacement strings + in the pronunciation dictionary. Update our model to reflect this. + + Arguments: + - cell: the cell that changed. + - path: the path of that cell. + - new_text: the new pronunciation dictionary replacement string. + - model: the model that the cell is part of. + """ + + thisIter = model.get_iter(path) + model.set(thisIter, REPLACEMENT, new_text) + + def pronunciationFocusChange(self, widget, event, isFocused): + """Callback for the pronunciation tree's focus-{in,out}-event signal.""" + + _settingsManager.setSetting('usePronunciationDictionary', not isFocused) + + def pronunciationCursorChanged(self, widget): + """Set the search column in the pronunciation dictionary tree view + depending upon which column the user currently has the cursor in. + """ + + [path, focusColumn] = self.pronunciationView.get_cursor() + if focusColumn: + noColumns = len(self.pronunciationView.get_columns()) + for i in range(0, noColumns): + col = self.pronunciationView.get_column(i) + if focusColumn == col: + self.pronunciationView.set_search_column(i) + break + + def _createPronunciationTreeView(self): + """Create the pronunciation dictionary tree view. The view is the + pronunciationTreeView GtkTreeView widget. The view will consist + of a list containing two columns: + ACTUAL - the actual text string (word). + REPLACEMENT - the string that is used to pronounce that word. + """ + + self.pronunciationView = self.get_widget("pronunciationTreeView") + + if self.pronunciationView.get_columns(): + for column in self.pronunciationView.get_columns(): + self.pronunciationView.remove_column(column) + + model = Gtk.ListStore(GObject.TYPE_STRING, + GObject.TYPE_STRING) + + # Initially setup the list store model based on the values of all + # existing entries in the pronunciation dictionary -- unless it's + # the default script. + # + if not self.script.app: + _profile = self.prefsDict.get('activeProfile')[1] + pronDict = _settingsManager.getPronunciations(_profile) + else: + pronDict = pronunciation_dict.pronunciation_dict + for pronKey in sorted(pronDict.keys()): + thisIter = model.append() + try: + actual, replacement = pronDict[pronKey] + except Exception: + # Try to do something sensible for the previous format of + # pronunciation dictionary entries. See bug #464754 for + # more details. + # + actual = pronKey + replacement = pronDict[pronKey] + model.set(thisIter, + ACTUAL, actual, + REPLACEMENT, replacement) + + self.pronunciationView.set_model(model) + + # Pronunciation Dictionary actual string (word) column (ACTUAL). + column = Gtk.TreeViewColumn(guilabels.DICTIONARY_ACTUAL_STRING) + column.set_min_width(250) + column.set_resizable(True) + renderer = Gtk.CellRendererText() + renderer.set_property('editable', True) + column.pack_end(renderer, True) + column.add_attribute(renderer, 'text', ACTUAL) + renderer.connect("edited", self.pronActualValueEdited, model) + self.pronunciationView.insert_column(column, 0) + + # Pronunciation Dictionary replacement string column (REPLACEMENT) + column = Gtk.TreeViewColumn(guilabels.DICTIONARY_REPLACEMENT_STRING) + renderer = Gtk.CellRendererText() + renderer.set_property('editable', True) + column.pack_end(renderer, True) + column.add_attribute(renderer, 'text', REPLACEMENT) + renderer.connect("edited", self.pronReplacementValueEdited, model) + self.pronunciationView.insert_column(column, 1) + + self.pronunciationModel = model + + # Connect a handler for when the user changes columns within the + # view, so that we can adjust the search column for item lookups. + # + self.pronunciationView.connect("cursor_changed", + self.pronunciationCursorChanged) + + self.pronunciationView.connect( + "focus_in_event", self.pronunciationFocusChange, True) + self.pronunciationView.connect( + "focus_out_event", self.pronunciationFocusChange, False) + + def _initGUIState(self): + """Adjust the settings of the various components on the + configuration GUI depending upon the users preferences. + """ + + prefs = self.prefsDict + + # Speech pane. + # + enable = prefs["enableSpeech"] + self.get_widget("speechSupportCheckButton").set_active(enable) + self.get_widget("speechOptionsGrid").set_sensitive(enable) + + enable = prefs["onlySpeakDisplayedText"] + self.get_widget("onlySpeakDisplayedTextCheckButton").set_active(enable) + self.get_widget("contextOptionsGrid").set_sensitive(not enable) + + if prefs["verbalizePunctuationStyle"] == \ + settings.PUNCTUATION_STYLE_NONE: + self.get_widget("noneButton").set_active(True) + elif prefs["verbalizePunctuationStyle"] == \ + settings.PUNCTUATION_STYLE_SOME: + self.get_widget("someButton").set_active(True) + elif prefs["verbalizePunctuationStyle"] == \ + settings.PUNCTUATION_STYLE_MOST: + self.get_widget("mostButton").set_active(True) + else: + self.get_widget("allButton").set_active(True) + + if prefs["speechVerbosityLevel"] == settings.VERBOSITY_LEVEL_BRIEF: + self.get_widget("speechBriefButton").set_active(True) + else: + self.get_widget("speechVerboseButton").set_active(True) + + self.get_widget("onlySpeakDisplayedTextCheckButton").set_active( + prefs["onlySpeakDisplayedText"]) + + self.get_widget("enableSpeechIndentationCheckButton").set_active(\ + prefs["enableSpeechIndentation"]) + + self.get_widget("speakBlankLinesCheckButton").set_active(\ + prefs["speakBlankLines"]) + self.get_widget("speakMultiCaseStringsAsWordsCheckButton").set_active(\ + prefs["speakMultiCaseStringsAsWords"]) + self.get_widget("speakNumbersAsDigitsCheckButton").set_active( + prefs.get("speakNumbersAsDigits", settings.speakNumbersAsDigits)) + self.get_widget("enableTutorialMessagesCheckButton").set_active(\ + prefs["enableTutorialMessages"]) + self.get_widget("enablePauseBreaksCheckButton").set_active(\ + prefs["enablePauseBreaks"]) + self.get_widget("enablePositionSpeakingCheckButton").set_active(\ + prefs["enablePositionSpeaking"]) + self.get_widget("enableMnemonicSpeakingCheckButton").set_active(\ + prefs["enableMnemonicSpeaking"]) + self.get_widget("speakMisspelledIndicatorCheckButton").set_active( + prefs.get("speakMisspelledIndicator", settings.speakMisspelledIndicator)) + self.get_widget("speakDescriptionCheckButton").set_active( + prefs.get("speakDescription", settings.speakDescription)) + self.get_widget("speakContextBlockquoteCheckButton").set_active( + prefs.get("speakContextBlockquote", settings.speakContextList)) + self.get_widget("speakContextLandmarkCheckButton").set_active( + prefs.get("speakContextLandmark", settings.speakContextLandmark)) + self.get_widget("speakContextNonLandmarkFormCheckButton").set_active( + prefs.get("speakContextNonLandmarkForm", settings.speakContextNonLandmarkForm)) + self.get_widget("speakContextListCheckButton").set_active( + prefs.get("speakContextList", settings.speakContextList)) + self.get_widget("speakContextPanelCheckButton").set_active( + prefs.get("speakContextPanel", settings.speakContextPanel)) + self.get_widget("speakContextTableCheckButton").set_active( + prefs.get("speakContextTable", settings.speakContextTable)) + + enable = prefs.get("messagesAreDetailed", settings.messagesAreDetailed) + self.get_widget("messagesAreDetailedCheckButton").set_active(enable) + + enable = prefs.get("useColorNames", settings.useColorNames) + self.get_widget("useColorNamesCheckButton").set_active(enable) + + enable = prefs.get("readFullRowInGUITable", settings.readFullRowInGUITable) + self.get_widget("readFullRowInGUITableCheckButton").set_active(enable) + + enable = prefs.get("readFullRowInDocumentTable", settings.readFullRowInDocumentTable) + self.get_widget("readFullRowInDocumentTableCheckButton").set_active(enable) + + enable = prefs.get("readFullRowInSpreadSheet", settings.readFullRowInSpreadSheet) + self.get_widget("readFullRowInSpreadSheetCheckButton").set_active(enable) + + style = prefs.get("capitalizationStyle", settings.capitalizationStyle) + combobox = self.get_widget("capitalizationStyle") + options = [guilabels.CAPITALIZATION_STYLE_NONE, + guilabels.CAPITALIZATION_STYLE_ICON, + guilabels.CAPITALIZATION_STYLE_SPELL] + self.populateComboBox(combobox, options) + if style == settings.CAPITALIZATION_STYLE_ICON: + value = guilabels.CAPITALIZATION_STYLE_ICON + elif style == settings.CAPITALIZATION_STYLE_SPELL: + value = guilabels.CAPITALIZATION_STYLE_SPELL + else: + value = guilabels.CAPITALIZATION_STYLE_NONE + combobox.set_active(options.index(value)) + + combobox2 = self.get_widget("dateFormatCombo") + sdtime = time.strftime + ltime = time.localtime + self.populateComboBox(combobox2, + [sdtime(messages.DATE_FORMAT_LOCALE, ltime()), + sdtime(messages.DATE_FORMAT_NUMBERS_DM, ltime()), + sdtime(messages.DATE_FORMAT_NUMBERS_MD, ltime()), + sdtime(messages.DATE_FORMAT_NUMBERS_DMY, ltime()), + sdtime(messages.DATE_FORMAT_NUMBERS_MDY, ltime()), + sdtime(messages.DATE_FORMAT_NUMBERS_YMD, ltime()), + sdtime(messages.DATE_FORMAT_FULL_DM, ltime()), + sdtime(messages.DATE_FORMAT_FULL_MD, ltime()), + sdtime(messages.DATE_FORMAT_FULL_DMY, ltime()), + sdtime(messages.DATE_FORMAT_FULL_MDY, ltime()), + sdtime(messages.DATE_FORMAT_FULL_YMD, ltime()), + sdtime(messages.DATE_FORMAT_ABBREVIATED_DM, ltime()), + sdtime(messages.DATE_FORMAT_ABBREVIATED_MD, ltime()), + sdtime(messages.DATE_FORMAT_ABBREVIATED_DMY, ltime()), + sdtime(messages.DATE_FORMAT_ABBREVIATED_MDY, ltime()), + sdtime(messages.DATE_FORMAT_ABBREVIATED_YMD, ltime()) + ]) + + indexdate = DATE_FORMAT_LOCALE + dateFormat = self.prefsDict["presentDateFormat"] + if dateFormat == messages.DATE_FORMAT_LOCALE: + indexdate = DATE_FORMAT_LOCALE + elif dateFormat == messages.DATE_FORMAT_NUMBERS_DM: + indexdate = DATE_FORMAT_NUMBERS_DM + elif dateFormat == messages.DATE_FORMAT_NUMBERS_MD: + indexdate = DATE_FORMAT_NUMBERS_MD + elif dateFormat == messages.DATE_FORMAT_NUMBERS_DMY: + indexdate = DATE_FORMAT_NUMBERS_DMY + elif dateFormat == messages.DATE_FORMAT_NUMBERS_MDY: + indexdate = DATE_FORMAT_NUMBERS_MDY + elif dateFormat == messages.DATE_FORMAT_NUMBERS_YMD: + indexdate = DATE_FORMAT_NUMBERS_YMD + elif dateFormat == messages.DATE_FORMAT_FULL_DM: + indexdate = DATE_FORMAT_FULL_DM + elif dateFormat == messages.DATE_FORMAT_FULL_MD: + indexdate = DATE_FORMAT_FULL_MD + elif dateFormat == messages.DATE_FORMAT_FULL_DMY: + indexdate = DATE_FORMAT_FULL_DMY + elif dateFormat == messages.DATE_FORMAT_FULL_MDY: + indexdate = DATE_FORMAT_FULL_MDY + elif dateFormat == messages.DATE_FORMAT_FULL_YMD: + indexdate = DATE_FORMAT_FULL_YMD + elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_DM: + indexdate = DATE_FORMAT_ABBREVIATED_DM + elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_MD: + indexdate = DATE_FORMAT_ABBREVIATED_MD + elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_DMY: + indexdate = DATE_FORMAT_ABBREVIATED_DMY + elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_MDY: + indexdate = DATE_FORMAT_ABBREVIATED_MDY + elif dateFormat == messages.DATE_FORMAT_ABBREVIATED_YMD: + indexdate = DATE_FORMAT_ABBREVIATED_YMD + combobox2.set_active (indexdate) + + combobox3 = self.get_widget("timeFormatCombo") + self.populateComboBox(combobox3, + [sdtime(messages.TIME_FORMAT_LOCALE, ltime()), + sdtime(messages.TIME_FORMAT_12_HM, ltime()), + sdtime(messages.TIME_FORMAT_12_HMS, ltime()), + sdtime(messages.TIME_FORMAT_24_HMS, ltime()), + sdtime(messages.TIME_FORMAT_24_HMS_WITH_WORDS, ltime()), + sdtime(messages.TIME_FORMAT_24_HM, ltime()), + sdtime(messages.TIME_FORMAT_24_HM_WITH_WORDS, ltime())]) + indextime = TIME_FORMAT_LOCALE + timeFormat = self.prefsDict["presentTimeFormat"] + if timeFormat == messages.TIME_FORMAT_LOCALE: + indextime = TIME_FORMAT_LOCALE + elif timeFormat == messages.TIME_FORMAT_12_HM: + indextime = TIME_FORMAT_12_HM + elif timeFormat == messages.TIME_FORMAT_12_HMS: + indextime = TIME_FORMAT_12_HMS + elif timeFormat == messages.TIME_FORMAT_24_HMS: + indextime = TIME_FORMAT_24_HMS + elif timeFormat == messages.TIME_FORMAT_24_HMS_WITH_WORDS: + indextime = TIME_FORMAT_24_HMS_WITH_WORDS + elif timeFormat == messages.TIME_FORMAT_24_HM: + indextime = TIME_FORMAT_24_HM + elif timeFormat == messages.TIME_FORMAT_24_HM_WITH_WORDS: + indextime = TIME_FORMAT_24_HM_WITH_WORDS + combobox3.set_active (indextime) + + self.get_widget("speakProgressBarUpdatesCheckButton").set_active( + prefs.get("speakProgressBarUpdates", settings.speakProgressBarUpdates)) + self.get_widget("brailleProgressBarUpdatesCheckButton").set_active( + prefs.get("brailleProgressBarUpdates", settings.brailleProgressBarUpdates)) + self.get_widget("beepProgressBarUpdatesCheckButton").set_active( + prefs.get("beepProgressBarUpdates", settings.beepProgressBarUpdates)) + + interval = prefs["progressBarUpdateInterval"] + self.get_widget("progressBarUpdateIntervalSpinButton").set_value(interval) + + comboBox = self.get_widget("progressBarVerbosity") + levels = [guilabels.PROGRESS_BAR_ALL, + guilabels.PROGRESS_BAR_APPLICATION, + guilabels.PROGRESS_BAR_WINDOW] + self.populateComboBox(comboBox, levels) + comboBox.set_active(prefs["progressBarVerbosity"]) + + enable = prefs["enableMouseReview"] + self.get_widget("enableMouseReviewCheckButton").set_active(enable) + + # Braille pane. + # + self.get_widget("enableBrailleCheckButton").set_active( \ + prefs["enableBraille"]) + state = prefs["brailleRolenameStyle"] == \ + settings.BRAILLE_ROLENAME_STYLE_SHORT + self.get_widget("abbrevRolenames").set_active(state) + + self.get_widget("disableBrailleEOLCheckButton").set_active( + prefs["disableBrailleEOL"]) + + if louis is None: + self.get_widget( \ + "contractedBrailleCheckButton").set_sensitive(False) + else: + self.get_widget("contractedBrailleCheckButton").set_active( \ + prefs["enableContractedBraille"]) + # Set up contraction table combo box and set it to the + # currently used one. + # + tablesCombo = self.get_widget("contractionTableCombo") + tableDict = braille.listTables() + selectedTableIter = None + selectedTable = prefs["brailleContractionTable"] or \ + braille.getDefaultTable() + if tableDict: + tablesModel = Gtk.ListStore(str, str) + names = sorted(tableDict.keys()) + for name in names: + fname = tableDict[name] + it = tablesModel.append([name, fname]) + if os.path.join(braille.tablesdir, fname) == \ + selectedTable: + selectedTableIter = it + cell = self.planeCellRendererText + tablesCombo.clear() + tablesCombo.pack_start(cell, True) + tablesCombo.add_attribute(cell, 'text', 0) + tablesCombo.set_model(tablesModel) + if selectedTableIter: + tablesCombo.set_active_iter(selectedTableIter) + else: + tablesCombo.set_active(0) + else: + tablesCombo.set_sensitive(False) + if prefs["brailleVerbosityLevel"] == settings.VERBOSITY_LEVEL_BRIEF: + self.get_widget("brailleBriefButton").set_active(True) + else: + self.get_widget("brailleVerboseButton").set_active(True) + + self.get_widget("enableBrailleWordWrapCheckButton").set_active( + prefs.get("enableBrailleWordWrap", settings.enableBrailleWordWrap)) + + selectionIndicator = prefs["brailleSelectorIndicator"] + if selectionIndicator == settings.BRAILLE_UNDERLINE_7: + self.get_widget("brailleSelection7Button").set_active(True) + elif selectionIndicator == settings.BRAILLE_UNDERLINE_8: + self.get_widget("brailleSelection8Button").set_active(True) + elif selectionIndicator == settings.BRAILLE_UNDERLINE_BOTH: + self.get_widget("brailleSelectionBothButton").set_active(True) + else: + self.get_widget("brailleSelectionNoneButton").set_active(True) + + linkIndicator = prefs["brailleLinkIndicator"] + if linkIndicator == settings.BRAILLE_UNDERLINE_7: + self.get_widget("brailleLink7Button").set_active(True) + elif linkIndicator == settings.BRAILLE_UNDERLINE_8: + self.get_widget("brailleLink8Button").set_active(True) + elif linkIndicator == settings.BRAILLE_UNDERLINE_BOTH: + self.get_widget("brailleLinkBothButton").set_active(True) + else: + self.get_widget("brailleLinkNoneButton").set_active(True) + + enable = prefs.get("enableFlashMessages", settings.enableFlashMessages) + self.get_widget("enableFlashMessagesCheckButton").set_active(enable) + + enable = prefs.get("flashIsPersistent", settings.flashIsPersistent) + self.get_widget("flashIsPersistentCheckButton").set_active(enable) + + enable = prefs.get("flashIsDetailed", settings.flashIsDetailed) + self.get_widget("flashIsDetailedCheckButton").set_active(enable) + + duration = prefs["brailleFlashTime"] + self.get_widget("brailleFlashTimeSpinButton").set_value(duration / 1000) + + # Key Echo pane. + # + self.get_widget("keyEchoCheckButton").set_active( \ + prefs["enableKeyEcho"]) + self.get_widget("enableAlphabeticKeysCheckButton").set_active( + prefs.get("enableAlphabeticKeys", settings.enableAlphabeticKeys)) + self.get_widget("enableNumericKeysCheckButton").set_active( + prefs.get("enableNumericKeys", settings.enableNumericKeys)) + self.get_widget("enablePunctuationKeysCheckButton").set_active( + prefs.get("enablePunctuationKeys", settings.enablePunctuationKeys)) + self.get_widget("enableSpaceCheckButton").set_active( + prefs.get("enableSpace", settings.enableSpace)) + self.get_widget("enableModifierKeysCheckButton").set_active( \ + prefs["enableModifierKeys"]) + self.get_widget("enableFunctionKeysCheckButton").set_active( \ + prefs["enableFunctionKeys"]) + self.get_widget("enableActionKeysCheckButton").set_active( \ + prefs["enableActionKeys"]) + self.get_widget("enableNavigationKeysCheckButton").set_active( \ + prefs["enableNavigationKeys"]) + self.get_widget("enableDiacriticalKeysCheckButton").set_active( \ + prefs["enableDiacriticalKeys"]) + self.get_widget("enableEchoByCharacterCheckButton").set_active( \ + prefs["enableEchoByCharacter"]) + self.get_widget("enableEchoByWordCheckButton").set_active( \ + prefs["enableEchoByWord"]) + self.get_widget("enableEchoBySentenceCheckButton").set_active( \ + prefs["enableEchoBySentence"]) + + # Text attributes pane. + # + self._createTextAttributesTreeView() + + brailleIndicator = prefs["textAttributesBrailleIndicator"] + if brailleIndicator == settings.BRAILLE_UNDERLINE_7: + self.get_widget("textBraille7Button").set_active(True) + elif brailleIndicator == settings.BRAILLE_UNDERLINE_8: + self.get_widget("textBraille8Button").set_active(True) + elif brailleIndicator == settings.BRAILLE_UNDERLINE_BOTH: + self.get_widget("textBrailleBothButton").set_active(True) + else: + self.get_widget("textBrailleNoneButton").set_active(True) + + # Pronunciation dictionary pane. + # + self._createPronunciationTreeView() + + # General pane. + # + self.get_widget("presentToolTipsCheckButton").set_active( + prefs["presentToolTips"]) + + if prefs["keyboardLayout"] == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP: + self.get_widget("generalDesktopButton").set_active(True) + else: + self.get_widget("generalLaptopButton").set_active(True) + + combobox = self.get_widget("sayAllStyle") + self.populateComboBox(combobox, [guilabels.SAY_ALL_STYLE_LINE, + guilabels.SAY_ALL_STYLE_SENTENCE]) + combobox.set_active(prefs["sayAllStyle"]) + self.get_widget("rewindAndFastForwardInSayAllCheckButton").set_active( + prefs.get("rewindAndFastForwardInSayAll", settings.rewindAndFastForwardInSayAll)) + self.get_widget("structNavInSayAllCheckButton").set_active( + prefs.get("structNavInSayAll", settings.structNavInSayAll)) + self.get_widget("sayAllContextBlockquoteCheckButton").set_active( + prefs.get("sayAllContextBlockquote", settings.sayAllContextBlockquote)) + self.get_widget("sayAllContextLandmarkCheckButton").set_active( + prefs.get("sayAllContextLandmark", settings.sayAllContextLandmark)) + self.get_widget("sayAllContextNonLandmarkFormCheckButton").set_active( + prefs.get("sayAllContextNonLandmarkForm", settings.sayAllContextNonLandmarkForm)) + self.get_widget("sayAllContextListCheckButton").set_active( + prefs.get("sayAllContextList", settings.sayAllContextList)) + self.get_widget("sayAllContextPanelCheckButton").set_active( + prefs.get("sayAllContextPanel", settings.sayAllContextPanel)) + self.get_widget("sayAllContextTableCheckButton").set_active( + prefs.get("sayAllContextTable", settings.sayAllContextTable)) + + # Cthulhu User Profiles + # + self.profilesCombo = self.get_widget('availableProfilesComboBox1') + self.startingProfileCombo = self.get_widget('availableProfilesComboBox2') + self.profilesComboModel = self.get_widget('model9') + self.__initProfileCombo() + if self.script.app: + self.get_widget('profilesFrame').set_sensitive(False) + + # AI Assistant settings + # + self._initAIState() + + def __initProfileCombo(self): + """Adding available profiles and setting active as the active one""" + + availableProfiles = self.__getAvailableProfiles() + self.profilesComboModel.clear() + + if not len(availableProfiles): + self.profilesComboModel.append(self._defaultProfile) + else: + for profile in availableProfiles: + self.profilesComboModel.append(profile) + + activeProfile = self.prefsDict.get('activeProfile') or self._defaultProfile + startingProfile = self.prefsDict.get('startingProfile') or self._defaultProfile + + activeProfileIter = self.getComboBoxIndex(self.profilesCombo, + activeProfile[0]) + startingProfileIter = self.getComboBoxIndex(self.startingProfileCombo, + startingProfile[0]) + self.profilesCombo.set_active(activeProfileIter) + self.startingProfileCombo.set_active(startingProfileIter) + + def __getAvailableProfiles(self): + """Get available user profiles.""" + return _settingsManager.availableProfiles() + + def _initAIState(self): + """Initialize AI Assistant tab widgets with current settings.""" + prefs = self.prefsDict + + # Store widget references + self.enableAICheckButton = self.get_widget("enableAICheckButton") + self.aiProviderCombo = self.get_widget("aiProviderCombo") + self.aiApiKeyEntry = self.get_widget("aiApiKeyEntry") + self.aiOllamaModelEntry = self.get_widget("aiOllamaModelEntry") + self.aiOllamaEndpointEntry = self.get_widget("aiOllamaEndpointEntry") + self.aiConfirmationCheckButton = self.get_widget("aiConfirmationCheckButton") + self.aiScreenshotQualityCombo = self.get_widget("aiScreenshotQualityCombo") + + # Set enable AI checkbox + enabled = prefs.get("aiAssistantEnabled", settings.aiAssistantEnabled) + self.enableAICheckButton.set_active(enabled) + + # Set provider combo + provider = prefs.get("aiProvider", settings.aiProvider) + providerIndex = 0 # Default to Claude Code + if provider == settings.AI_PROVIDER_CLAUDE: + providerIndex = 1 + elif provider == settings.AI_PROVIDER_CHATGPT: + providerIndex = 2 + elif provider == settings.AI_PROVIDER_GEMINI: + providerIndex = 3 + elif provider == settings.AI_PROVIDER_OLLAMA: + providerIndex = 4 + self.aiProviderCombo.set_active(providerIndex) + + # Set API key file + apiKeyFile = prefs.get("aiApiKeyFile", settings.aiApiKeyFile) + self.aiApiKeyEntry.set_text(apiKeyFile) + + # Set Ollama model + ollamaModel = prefs.get("aiOllamaModel", settings.aiOllamaModel) + self.aiOllamaModelEntry.set_text(ollamaModel) + + # Set Ollama endpoint + ollamaEndpoint = prefs.get("aiOllamaEndpoint", settings.aiOllamaEndpoint) + self.aiOllamaEndpointEntry.set_text(ollamaEndpoint) + + # Set confirmation checkbox + confirmationRequired = prefs.get("aiConfirmationRequired", settings.aiConfirmationRequired) + self.aiConfirmationCheckButton.set_active(confirmationRequired) + + # Set screenshot quality combo + quality = prefs.get("aiScreenshotQuality", settings.aiScreenshotQuality) + qualityIndex = 1 # Default to medium + if quality == settings.AI_SCREENSHOT_QUALITY_LOW: + qualityIndex = 0 + elif quality == settings.AI_SCREENSHOT_QUALITY_HIGH: + qualityIndex = 2 + self.aiScreenshotQualityCombo.set_active(qualityIndex) + + # Enable/disable controls based on AI enabled state + self._updateAIControlsState(enabled) + + def _updateAIControlsState(self, enabled): + """Enable or disable AI controls based on AI enabled state.""" + self.aiProviderCombo.set_sensitive(enabled) + self.aiApiKeyEntry.set_sensitive(enabled) + self.aiOllamaModelEntry.set_sensitive(enabled) + self.aiOllamaEndpointEntry.set_sensitive(enabled) + self.aiConfirmationCheckButton.set_sensitive(enabled) + self.aiScreenshotQualityCombo.set_sensitive(enabled) + try: + self.get_widget("aiGetClaudeKeyButton").set_sensitive(enabled) + except: + pass # Button might not exist in older UI files + + # Update provider-specific controls if AI is enabled + if enabled: + current_provider = self.prefsDict.get("aiProvider", settings.aiProvider) + self._updateProviderControls(current_provider) + + def _updateProviderControls(self, provider): + """Update visibility/sensitivity of provider-specific controls.""" + # API key controls (needed for Claude, ChatGPT, Gemini - not for Claude Code or Ollama) + api_key_needed = provider in [settings.AI_PROVIDER_CLAUDE, settings.AI_PROVIDER_CHATGPT, settings.AI_PROVIDER_GEMINI] + self.aiApiKeyEntry.set_sensitive(api_key_needed) + + # Get Claude API Key button (only for Claude Code) + try: + claude_button = self.get_widget("aiGetClaudeKeyButton") + claude_button.set_visible(provider == settings.AI_PROVIDER_CLAUDE_CODE) + except: + pass # Button might not exist + + # Ollama model and endpoint entries (only for Ollama) + ollama_enabled = provider == settings.AI_PROVIDER_OLLAMA + self.aiOllamaModelEntry.set_sensitive(ollama_enabled) + self.aiOllamaEndpointEntry.set_sensitive(ollama_enabled) + + # Update labels based on provider + if provider == settings.AI_PROVIDER_CLAUDE_CODE: + self.aiApiKeyEntry.set_placeholder_text("No API key needed - uses Claude Code CLI") + elif provider == settings.AI_PROVIDER_OLLAMA: + self.aiApiKeyEntry.set_placeholder_text("No API key needed - uses local Ollama") + else: + self.aiApiKeyEntry.set_placeholder_text("Path to API key file") + + def _updateCthulhuModifier(self): + combobox = self.get_widget("cthulhuModifierComboBox") + keystring = ", ".join(self.prefsDict["cthulhuModifierKeys"]) + combobox.set_active(self.getComboBoxIndex(combobox, keystring)) + + def populateComboBox(self, combobox, items): + """Populates the combobox with the items provided. + + Arguments: + - combobox: the GtkComboBox to populate + - items: the list of strings with which to populate it + """ + + model = Gtk.ListStore(str) + for item in items: + model.append([item]) + combobox.set_model(model) + + def getComboBoxIndex(self, combobox, searchStr, col=0): + """ For each of the entries in the given combo box, look for searchStr. + Return the index of the entry if searchStr is found. + + Arguments: + - combobox: the GtkComboBox to search. + - searchStr: the string to search for. + + Returns the index of the first entry in combobox with searchStr, or + 0 if not found. + """ + + model = combobox.get_model() + myiter = model.get_iter_first() + for i in range(0, len(model)): + name = model.get_value(myiter, col) + if name == searchStr: + return i + myiter = model.iter_next(myiter) + + return 0 + + def getComboBoxList(self, combobox): + """Get the list of values from the active combox + """ + active = combobox.get_active() + model = combobox.get_model() + activeIter = model.get_iter(active) + activeLabel = model.get_value(activeIter, 0) + activeName = model.get_value(activeIter, 1) + return [activeLabel, activeName] + + def getKeyBindingsModelDict(self, model, modifiedOnly=True): + modelDict = {} + node = model.get_iter_first() + while node: + child = model.iter_children(node) + while child: + key, modified = model.get(child, HANDLER, MODIF) + if modified or not modifiedOnly: + value = [] + value.append(list(model.get( + child, KEY1, MOD_MASK1, MOD_USED1, CLICK_COUNT1))) + modelDict[key] = value + child = model.iter_next(child) + node = model.iter_next(node) + + return modelDict + + def getModelDict(self, model): + """Get the list of values from a list[str,str] model + """ + pronunciation_dict.pronunciation_dict = {} + currentIter = model.get_iter_first() + while currentIter is not None: + key, value = model.get(currentIter, ACTUAL, REPLACEMENT) + if key and value: + pronunciation_dict.setPronunciation(key, value) + currentIter = model.iter_next(currentIter) + modelDict = pronunciation_dict.pronunciation_dict + return modelDict + + def showGUI(self): + """Show the Cthulhu configuration GUI window. This assumes that + the GUI has already been created. + """ + + cthulhuSetupWindow = self.get_widget("cthulhuSetupWindow") + + accelGroup = Gtk.AccelGroup() + cthulhuSetupWindow.add_accel_group(accelGroup) + helpButton = self.get_widget("helpButton") + (keyVal, modifierMask) = Gtk.accelerator_parse("F1") + helpButton.add_accelerator("clicked", + accelGroup, + keyVal, + modifierMask, + 0) + + try: + ts = cthulhu_state.lastInputEvent.timestamp + # Ensure timestamp fits in 32-bit range for GTK + if ts > 4294967295: # 2^32 - 1 + ts = ts % 4294967296 # Wrap to 32-bit range + except Exception: + ts = 0 + if ts == 0: + ts = Gtk.get_current_event_time() + cthulhuSetupWindow.present_with_time(int(ts)) + + # We always want to re-order the text attributes page so that enabled + # items are consistently at the top. + # + self._setSpokenTextAttributes( + self.getTextAttributesView, + _settingsManager.getSetting('enabledSpokenTextAttributes'), + True, True) + + if self.script.app: + title = guilabels.PREFERENCES_APPLICATION_TITLE % AXObject.get_name(self.script.app) + cthulhuSetupWindow.set_title(title) + + cthulhuSetupWindow.show() + + def _initComboBox(self, combobox): + """Initialize the given combo box to take a list of int/str pairs. + + Arguments: + - combobox: the GtkComboBox to initialize. + """ + + cell = Gtk.CellRendererText() + combobox.pack_start(cell, True) + # We only want to display one column; not two. + # + try: + columnToDisplay = combobox.get_cells()[0] + combobox.add_attribute(columnToDisplay, 'text', 1) + except Exception: + combobox.add_attribute(cell, 'text', 1) + model = Gtk.ListStore(int, str) + combobox.set_model(model) + + # Force the display comboboxes to be left aligned. + # + if isinstance(combobox, Gtk.ComboBoxText): + size = combobox.size_request() + cell.set_fixed_size(size[0] - 29, -1) + + return model + + def _setKeyEchoItems(self): + """[In]sensitize the checkboxes for the various types of key echo, + depending upon whether the value of the key echo check button is set. + """ + + enable = self.get_widget("keyEchoCheckButton").get_active() + self.get_widget("enableAlphabeticKeysCheckButton").set_sensitive(enable) + self.get_widget("enableNumericKeysCheckButton").set_sensitive(enable) + self.get_widget("enablePunctuationKeysCheckButton").set_sensitive(enable) + self.get_widget("enableSpaceCheckButton").set_sensitive(enable) + self.get_widget("enableModifierKeysCheckButton").set_sensitive(enable) + self.get_widget("enableFunctionKeysCheckButton").set_sensitive(enable) + self.get_widget("enableActionKeysCheckButton").set_sensitive(enable) + self.get_widget("enableNavigationKeysCheckButton").set_sensitive(enable) + self.get_widget("enableDiacriticalKeysCheckButton").set_sensitive( \ + enable) + + def _presentMessage(self, text, interrupt=False): + """If the text field is not None, presents the given text, optionally + interrupting anything currently being spoken. + + Arguments: + - text: the text to present + - interrupt: if True, interrupt any speech currently being spoken + """ + + self.script.speakMessage(text, interrupt=interrupt) + try: + self.script.displayBrailleMessage(text, flashTime=-1) + except Exception: + pass + + def _createNode(self, appName): + """Create a new root node in the TreeStore model with the name of the + application. + + Arguments: + - appName: the name of the TreeStore Node (the same of the application) + """ + + model = self.keyBindingsModel + + myiter = model.append(None) + model.set_value(myiter, DESCRIP, appName) + model.set_value(myiter, MODIF, False) + + return myiter + + def _getIterOf(self, appName): + """Returns the Gtk.TreeIter of the TreeStore model + that matches the application name passed as argument + + Arguments: + - appName: a string with the name of the application of the node wanted + it's the same that the field DESCRIP of the model treeStore + """ + + model = self.keyBindingsModel + + for row in model: + if ((model.iter_depth(row.iter) == 0) \ + and (row[DESCRIP] == appName)): + return row.iter + + return None + + def _clickCountToString(self, clickCount): + """Given a numeric clickCount, returns a string for inclusion + in the list of keybindings. + + Argument: + - clickCount: the number of clicks associated with the keybinding. + """ + + clickCountString = "" + if clickCount == 2: + clickCountString = f" ({guilabels.CLICK_COUNT_DOUBLE})" + elif clickCount == 3: + clickCountString = f" ({guilabels.CLICK_COUNT_TRIPLE})" + + return clickCountString + + def _insertRow(self, handl, kb, parent=None, modif=False): + """Appends a new row with the new keybinding data to the treeview + + Arguments: + - handl: the name of the handler associated to the keyBinding + - kb: the new keybinding. + - parent: the parent node of the treeview, where to append the kb + - modif: whether to check the modified field or not. + + Returns a Gtk.TreeIter pointing at the new row. + """ + + model = self.keyBindingsModel + + if parent is None: + parent = self._getIterOf(guilabels.KB_GROUP_DEFAULT) + + if parent is not None: + myiter = model.append(parent) + if not kb.keysymstring: + text = None + else: + clickCount = self._clickCountToString(kb.click_count) + keysymstring = kb.keysymstring + text = keybindings.getModifierNames(kb.modifiers) \ + + keysymstring \ + + clickCount + + model.set_value(myiter, HANDLER, handl) + model.set_value(myiter, DESCRIP, kb.handler.description) + model.set_value(myiter, MOD_MASK1, str(kb.modifier_mask)) + model.set_value(myiter, MOD_USED1, str(kb.modifiers)) + model.set_value(myiter, KEY1, kb.keysymstring) + model.set_value(myiter, CLICK_COUNT1, str(kb.click_count)) + if text is not None: + model.set_value(myiter, OLDTEXT1, text) + model.set_value(myiter, TEXT1, text) + model.set_value(myiter, MODIF, modif) + model.set_value(myiter, EDITABLE, True) + + return myiter + else: + return None + + def _insertRowBraille(self, handl, com, inputEvHand, + parent=None, modif=False): + """Appends a new row with the new braille binding data to the treeview + + Arguments: + - handl: the name of the handler associated to the brailleBinding + - com: the BrlTTY command + - inputEvHand: the inputEventHandler with the new brailleBinding + - parent: the parent node of the treeview, where to append the kb + - modif: whether to check the modified field or not. + + Returns a Gtk.TreeIter pointing at the new row. + """ + + model = self.keyBindingsModel + + if parent is None: + parent = self._getIterOf(guilabels.KB_GROUP_BRAILLE) + + if parent is not None: + myiter = model.append(parent) + model.set_value(myiter, HANDLER, handl) + model.set_value(myiter, DESCRIP, inputEvHand.description) + model.set_value(myiter, KEY1, str(com)) + model.set_value(myiter, TEXT1, braille.command_name[com]) + model.set_value(myiter, MODIF, modif) + model.set_value(myiter, EDITABLE, False) + return myiter + else: + return None + + def _markModified(self): + """ Mark as modified the user custom key bindings: + """ + + try: + self.script.setupInputEventHandlers() + keyBinds = keybindings.KeyBindings() + keyBinds = _settingsManager.overrideKeyBindings(self.script, keyBinds) + keyBind = keybindings.KeyBinding(None, None, None, None) + treeModel = self.keyBindingsModel + + myiter = treeModel.get_iter_first() + while myiter is not None: + iterChild = treeModel.iter_children(myiter) + while iterChild is not None: + descrip = treeModel.get_value(iterChild, DESCRIP) + keyBind.handler = \ + input_event.InputEventHandler(None, descrip) + if keyBinds.hasKeyBinding(keyBind, + typeOfSearch="description"): + treeModel.set_value(iterChild, MODIF, True) + iterChild = treeModel.iter_next(iterChild) + myiter = treeModel.iter_next(myiter) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + def _populateKeyBindings(self, clearModel=True): + """Fills the TreeView with the list of Cthulhu keybindings + + Arguments: + - clearModel: if True, initially clear out the key bindings model. + """ + + self.keyBindView.set_model(None) + self.keyBindView.set_headers_visible(False) + self.keyBindView.hide() + if clearModel: + self.keyBindingsModel.clear() + self.kbindings = None + + appName = AXObject.get_name(self.script.app) + iterApp = self._createNode(appName) + iterCthulhu = self._createNode(guilabels.KB_GROUP_DEFAULT) + iterUnbound = self._createNode(guilabels.KB_GROUP_UNBOUND) + iterNotificationPresenter = self._createNode(guilabels.KB_GROUP_NOTIFICATIONS) + iterFlatReviewPresenter = self._createNode(guilabels.KB_GROUP_FLAT_REVIEW) + iterSpeechAndVerbosity = self._createNode(guilabels.KB_GROUP_SPEECH_VERBOSITY) + iterDateAndTime = self._createNode(guilabels.KB_GROUP_DATE_AND_TIME) + iterBookmarks = self._createNode(guilabels.KB_GROUP_BOOKMARKS) + iterObjectNav = self._createNode(guilabels.KB_GROUP_OBJECT_NAVIGATION) + iterWhereAmIPresenter = self._createNode(guilabels.KB_GROUP_WHERE_AM_I) + iterLearnMode = self._createNode(guilabels.KB_GROUP_LEARN_MODE) + iterMouseReviewer = self._createNode(guilabels.KB_GROUP_MOUSE_REVIEW) + iterActionPresenter = self._createNode(guilabels.KB_GROUP_ACTIONS) + + if not self.kbindings: + self.kbindings = keybindings.KeyBindings() + self.script.setupInputEventHandlers() + allKeyBindings = self.script.getKeyBindings() + defKeyBindings = self.script.getDefaultKeyBindings() + npKeyBindings = self.script.getNotificationPresenter().get_bindings() + svKeyBindings = self.script.getSpeechAndVerbosityManager().get_bindings() + dtKeyBindings = self.script.getDateAndTimePresenter().get_bindings() + bmKeyBindings = self.script.getBookmarks().get_bindings() + onKeyBindings = self.script.getObjectNavigator().get_bindings() + lmKeyBindings = self.script.getLearnModePresenter().get_bindings() + mrKeyBindings = self.script.getMouseReviewer().get_bindings() + acKeyBindings = self.script.getActionPresenter().get_bindings() + + layout = _settingsManager.getSetting('keyboardLayout') + isDesktop = layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP + frKeyBindings = self.script.getFlatReviewPresenter().get_bindings(isDesktop) + waiKeyBindings = self.script.getWhereAmIPresenter().get_bindings(isDesktop) + + for kb in allKeyBindings.keyBindings: + if not self.kbindings.hasKeyBinding(kb, "strict"): + handl = self.script.getInputEventHandlerKey(kb.handler) + if npKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterNotificationPresenter) + elif onKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterObjectNav) + elif frKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterFlatReviewPresenter) + elif waiKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterWhereAmIPresenter) + elif svKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterSpeechAndVerbosity) + elif dtKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterDateAndTime) + elif bmKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterBookmarks) + elif lmKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterLearnMode) + elif acKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterActionPresenter) + elif mrKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterMouseReviewer) + elif not defKeyBindings.hasKeyBinding(kb, "description"): + self._insertRow(handl, kb, iterApp) + elif kb.keysymstring: + self._insertRow(handl, kb, iterCthulhu) + else: + self._insertRow(handl, kb, iterUnbound) + self.kbindings.add(kb) + + if not self.keyBindingsModel.iter_has_child(iterApp): + self.keyBindingsModel.remove(iterApp) + + if not self.keyBindingsModel.iter_has_child(iterUnbound): + self.keyBindingsModel.remove(iterUnbound) + + self._updateCthulhuModifier() + self._markModified() + iterBB = self._createNode(guilabels.KB_GROUP_BRAILLE) + self.bbindings = self.script.getBrailleBindings() + for com, inputEvHand in self.bbindings.items(): + handl = self.script.getInputEventHandlerKey(inputEvHand) + self._insertRowBraille(handl, com, inputEvHand, iterBB) + + self.keyBindView.set_model(self.keyBindingsModel) + self.keyBindView.set_headers_visible(True) + self.keyBindingsModel.set_sort_column_id(OLDTEXT1, Gtk.SortType.ASCENDING) + self.keyBindView.show() + + # Keep track of new/unbound keybindings that have yet to be applied. + # + self.pendingKeyBindings = {} + + def _cleanupSpeechServers(self): + """Remove unwanted factories and drivers for the current active + factory, when the user dismisses the Cthulhu Preferences dialog.""" + + for workingFactory in self.workingFactories: + if not (workingFactory == self.speechSystemsChoice): + workingFactory.SpeechServer.shutdownActiveServers() + else: + servers = workingFactory.SpeechServer.getSpeechServers() + for server in servers: + if not (server == self.speechServersChoice): + server.shutdown() + + def speechSupportChecked(self, widget): + """Signal handler for the "toggled" signal for the + speechSupportCheckButton GtkCheckButton widget. The user has + [un]checked the 'Enable Speech' checkbox. Set the 'enableSpeech' + preference to the new value. Set the rest of the speech pane items + [in]sensensitive depending upon whether this checkbox is checked. + + Arguments: + - widget: the component that generated the signal. + """ + + enable = widget.get_active() + self.prefsDict["enableSpeech"] = enable + self.get_widget("speechOptionsGrid").set_sensitive(enable) + + def onlySpeakDisplayedTextToggled(self, widget): + """Signal handler for the "toggled" signal for the GtkCheckButton + onlySpeakDisplayedText. In addition to updating the preferences, + set the sensitivity of the contextOptionsGrid. + + Arguments: + - widget: the component that generated the signal. + """ + + enable = widget.get_active() + self.prefsDict["onlySpeakDisplayedText"] = enable + self.get_widget("contextOptionsGrid").set_sensitive(not enable) + + def speechSystemsChanged(self, widget): + """Signal handler for the "changed" signal for the speechSystems + GtkComboBox widget. The user has selected a different speech + system. Clear the existing list of speech servers, and setup + a new list of speech servers based on the new choice. Setup a + new list of voices for the first speech server in the list. + + Arguments: + - widget: the component that generated the signal. + """ + + if self.initializingSpeech: + return + + selectedIndex = widget.get_active() + self.speechSystemsChoice = self.speechSystemsChoices[selectedIndex] + self._setupSpeechServers() + + def speechServersChanged(self, widget): + """Signal handler for the "changed" signal for the speechServers + GtkComboBox widget. The user has selected a different speech + server. Clear the existing list of voices, and setup a new + list of voices based on the new choice. + + Arguments: + - widget: the component that generated the signal. + """ + + if self.initializingSpeech: + return + + selectedIndex = widget.get_active() + self.speechServersChoice = self.speechServersChoices[selectedIndex] + + # Whenever the speech servers change, we need to make sure we + # clear whatever family was in use by the current voice types. + # Otherwise, we can end up with family names from one server + # bleeding over (e.g., "Paul" from Fonix ends up getting in + # the "Default" voice type after we switch to eSpeak). + # + try: + del self.defaultVoice[acss.ACSS.FAMILY] + del self.uppercaseVoice[acss.ACSS.FAMILY] + del self.hyperlinkVoice[acss.ACSS.FAMILY] + del self.systemVoice[acss.ACSS.FAMILY] + except Exception: + pass + + self._setupVoices() + + def speechLanguagesChanged(self, widget): + """Signal handler for the "value_changed" signal for the languages + GtkComboBox widget. The user has selected a different voice + language. Save the new voice language name based on the new choice. + + Arguments: + - widget: the component that generated the signal. + """ + + if self.initializingSpeech: + return + + selectedIndex = widget.get_active() + try: + self.speechLanguagesChoice = self.speechLanguagesChoices[selectedIndex] + if (self.speechServersChoice, self.speechLanguagesChoice) in \ + self.selectedFamilyChoices: + i = self.selectedFamilyChoices[self.speechServersChoice, \ + self.speechLanguagesChoice] + family = self.speechFamiliesChoices[i] + name = family[speechserver.VoiceFamily.NAME] + language = family[speechserver.VoiceFamily.LANG] + dialect = family[speechserver.VoiceFamily.DIALECT] + variant = family[speechserver.VoiceFamily.VARIANT] + voiceType = self.get_widget("voiceTypesCombo").get_active() + self._setFamilyNameForVoiceType(voiceType, name, language, dialect, variant) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + # Remember the last family manually selected by the user for the + # current speech server. + # + if not selectedIndex == -1: + self.selectedLanguageChoices[self.speechServersChoice] = selectedIndex + + self._setupFamilies() + + def speechFamiliesChanged(self, widget): + """Signal handler for the "value_changed" signal for the families + GtkComboBox widget. The user has selected a different voice + family. Save the new voice family name based on the new choice. + + Arguments: + - widget: the component that generated the signal. + """ + + if self.initializingSpeech: + return + + selectedIndex = widget.get_active() + try: + family = self.speechFamiliesChoices[selectedIndex] + name = family[speechserver.VoiceFamily.NAME] + language = family[speechserver.VoiceFamily.LANG] + dialect = family[speechserver.VoiceFamily.DIALECT] + variant = family[speechserver.VoiceFamily.VARIANT] + voiceType = self.get_widget("voiceTypesCombo").get_active() + self._setFamilyNameForVoiceType(voiceType, name, language, dialect, variant) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + # Remember the last family manually selected by the user for the + # current speech server. + # + if not selectedIndex == -1: + self.selectedFamilyChoices[self.speechServersChoice, \ + self.speechLanguagesChoice] = selectedIndex + + def voiceTypesChanged(self, widget): + """Signal handler for the "changed" signal for the voiceTypes + GtkComboBox widget. The user has selected a different voice + type. Setup the new family, rate, pitch and volume component + values based on the new choice. + + Arguments: + - widget: the component that generated the signal. + """ + + if self.initializingSpeech: + return + + voiceType = widget.get_active() + self._setVoiceSettingsForVoiceType(voiceType) + + def rateValueChanged(self, widget): + """Signal handler for the "value_changed" signal for the rateScale + GtkScale widget. The user has changed the current rate value. + Save the new rate value based on the currently selected voice + type. + + Arguments: + - widget: the component that generated the signal. + """ + + rate = widget.get_value() + voiceType = self.get_widget("voiceTypesCombo").get_active() + self._setRateForVoiceType(voiceType, rate) + voices = _settingsManager.getSetting('voices') + voices.get(settings.DEFAULT_VOICE, {})[acss.ACSS.RATE] = rate + _settingsManager.setSetting('voices', voices) + + def pitchValueChanged(self, widget): + """Signal handler for the "value_changed" signal for the pitchScale + GtkScale widget. The user has changed the current pitch value. + Save the new pitch value based on the currently selected voice + type. + + Arguments: + - widget: the component that generated the signal. + """ + + pitch = widget.get_value() + voiceType = self.get_widget("voiceTypesCombo").get_active() + self._setPitchForVoiceType(voiceType, pitch) + voices = _settingsManager.getSetting('voices') + voices.get(settings.DEFAULT_VOICE, {})[acss.ACSS.AVERAGE_PITCH] = pitch + _settingsManager.setSetting('voices', voices) + + def volumeValueChanged(self, widget): + """Signal handler for the "value_changed" signal for the voiceScale + GtkScale widget. The user has changed the current volume value. + Save the new volume value based on the currently selected voice + type. + + Arguments: + - widget: the component that generated the signal. + """ + + volume = widget.get_value() + voiceType = self.get_widget("voiceTypesCombo").get_active() + self._setVolumeForVoiceType(voiceType, volume) + voices = _settingsManager.getSetting('voices') + voices.get(settings.DEFAULT_VOICE, {})[acss.ACSS.GAIN] = volume + _settingsManager.setSetting('voices', voices) + + def checkButtonToggled(self, widget): + """Signal handler for "toggled" signal for basic GtkCheckButton + widgets. The user has altered the state of the checkbox. + Set the preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + # To use this default handler please make sure: + # The name of the setting that will be changed is: settingName + # The id of the widget in the ui should be: settingNameCheckButton + # + settingName = Gtk.Buildable.get_name(widget) + # strip "CheckButton" from the end. + settingName = settingName[:-11] + self.prefsDict[settingName] = widget.get_active() + + def keyEchoChecked(self, widget): + """Signal handler for the "toggled" signal for the + keyEchoCheckbutton GtkCheckButton widget. The user has + [un]checked the 'Enable Key Echo' checkbox. Set the + 'enableKeyEcho' preference to the new value. [In]sensitize + the checkboxes for the various types of key echo, depending + upon whether this value is checked or unchecked. + + Arguments: + - widget: the component that generated the signal. + """ + + self.prefsDict["enableKeyEcho"] = widget.get_active() + self._setKeyEchoItems() + + def brailleSelectionChanged(self, widget): + """Signal handler for the "toggled" signal for the + brailleSelectionNoneButton, brailleSelection7Button, + brailleSelection8Button or brailleSelectionBothButton + GtkRadioButton widgets. The user has toggled the braille + selection indicator value. If this signal was generated + as the result of a radio button getting selected (as + opposed to a radio button losing the selection), set the + 'brailleSelectorIndicator' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.BRAILLE_DOT_7: + self.prefsDict["brailleSelectorIndicator"] = \ + settings.BRAILLE_UNDERLINE_7 + elif widget.get_label() == guilabels.BRAILLE_DOT_8: + self.prefsDict["brailleSelectorIndicator"] = \ + settings.BRAILLE_UNDERLINE_8 + elif widget.get_label() == guilabels.BRAILLE_DOT_7_8: + self.prefsDict["brailleSelectorIndicator"] = \ + settings.BRAILLE_UNDERLINE_BOTH + else: + self.prefsDict["brailleSelectorIndicator"] = \ + settings.BRAILLE_UNDERLINE_NONE + + def brailleLinkChanged(self, widget): + """Signal handler for the "toggled" signal for the + brailleLinkNoneButton, brailleLink7Button, + brailleLink8Button or brailleLinkBothButton + GtkRadioButton widgets. The user has toggled the braille + link indicator value. If this signal was generated + as the result of a radio button getting selected (as + opposed to a radio button losing the selection), set the + 'brailleLinkIndicator' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.BRAILLE_DOT_7: + self.prefsDict["brailleLinkIndicator"] = \ + settings.BRAILLE_UNDERLINE_7 + elif widget.get_label() == guilabels.BRAILLE_DOT_8: + self.prefsDict["brailleLinkIndicator"] = \ + settings.BRAILLE_UNDERLINE_8 + elif widget.get_label() == guilabels.BRAILLE_DOT_7_8: + self.prefsDict["brailleLinkIndicator"] = \ + settings.BRAILLE_UNDERLINE_BOTH + else: + self.prefsDict["brailleLinkIndicator"] = \ + settings.BRAILLE_UNDERLINE_NONE + + def brailleIndicatorChanged(self, widget): + """Signal handler for the "toggled" signal for the + textBrailleNoneButton, textBraille7Button, textBraille8Button + or textBrailleBothButton GtkRadioButton widgets. The user has + toggled the text attributes braille indicator value. If this signal + was generated as the result of a radio button getting selected + (as opposed to a radio button losing the selection), set the + 'textAttributesBrailleIndicator' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.BRAILLE_DOT_7: + self.prefsDict["textAttributesBrailleIndicator"] = \ + settings.BRAILLE_UNDERLINE_7 + elif widget.get_label() == guilabels.BRAILLE_DOT_8: + self.prefsDict["textAttributesBrailleIndicator"] = \ + settings.BRAILLE_UNDERLINE_8 + elif widget.get_label() == guilabels.BRAILLE_DOT_7_8: + self.prefsDict["textAttributesBrailleIndicator"] = \ + settings.BRAILLE_UNDERLINE_BOTH + else: + self.prefsDict["textAttributesBrailleIndicator"] = \ + settings.BRAILLE_UNDERLINE_NONE + + def punctuationLevelChanged(self, widget): + """Signal handler for the "toggled" signal for the noneButton, + someButton or allButton GtkRadioButton widgets. The user has + toggled the speech punctuation level value. If this signal + was generated as the result of a radio button getting selected + (as opposed to a radio button losing the selection), set the + 'verbalizePunctuationStyle' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.PUNCTUATION_STYLE_NONE: + self.prefsDict["verbalizePunctuationStyle"] = \ + settings.PUNCTUATION_STYLE_NONE + elif widget.get_label() == guilabels.PUNCTUATION_STYLE_SOME: + self.prefsDict["verbalizePunctuationStyle"] = \ + settings.PUNCTUATION_STYLE_SOME + elif widget.get_label() == guilabels.PUNCTUATION_STYLE_MOST: + self.prefsDict["verbalizePunctuationStyle"] = \ + settings.PUNCTUATION_STYLE_MOST + else: + self.prefsDict["verbalizePunctuationStyle"] = \ + settings.PUNCTUATION_STYLE_ALL + + def cthulhuModifierChanged(self, widget): + """Signal handler for the changed signal for the cthulhuModifierComboBox + Set the 'cthulhuModifierKeys' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + model = widget.get_model() + myIter = widget.get_active_iter() + cthulhuModifier = model[myIter][0] + self.prefsDict["cthulhuModifierKeys"] = cthulhuModifier.split(', ') + + def progressBarVerbosityChanged(self, widget): + """Signal handler for the changed signal for the progressBarVerbosity + GtkComboBox widget. Set the 'progressBarVerbosity' preference to + the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + model = widget.get_model() + myIter = widget.get_active_iter() + progressBarVerbosity = model[myIter][0] + if progressBarVerbosity == guilabels.PROGRESS_BAR_ALL: + self.prefsDict["progressBarVerbosity"] = \ + settings.PROGRESS_BAR_ALL + elif progressBarVerbosity == guilabels.PROGRESS_BAR_WINDOW: + self.prefsDict["progressBarVerbosity"] = \ + settings.PROGRESS_BAR_WINDOW + else: + self.prefsDict["progressBarVerbosity"] = \ + settings.PROGRESS_BAR_APPLICATION + + def capitalizationStyleChanged(self, widget): + model = widget.get_model() + myIter = widget.get_active_iter() + capitalizationStyle = model[myIter][0] + if capitalizationStyle == guilabels.CAPITALIZATION_STYLE_ICON: + self.prefsDict["capitalizationStyle"] = settings.CAPITALIZATION_STYLE_ICON + elif capitalizationStyle == guilabels.CAPITALIZATION_STYLE_SPELL: + self.prefsDict["capitalizationStyle"] = settings.CAPITALIZATION_STYLE_SPELL + else: + self.prefsDict["capitalizationStyle"] = settings.CAPITALIZATION_STYLE_NONE + self.script.speechAndVerbosityManager.update_capitalization_style() + + def sayAllStyleChanged(self, widget): + """Signal handler for the "changed" signal for the sayAllStyle + GtkComboBox widget. Set the 'sayAllStyle' preference to the + new value. + + Arguments: + - widget: the component that generated the signal. + """ + + model = widget.get_model() + myIter = widget.get_active_iter() + sayAllStyle = model[myIter][0] + if sayAllStyle == guilabels.SAY_ALL_STYLE_LINE: + self.prefsDict["sayAllStyle"] = settings.SAYALL_STYLE_LINE + elif sayAllStyle == guilabels.SAY_ALL_STYLE_SENTENCE: + self.prefsDict["sayAllStyle"] = settings.SAYALL_STYLE_SENTENCE + + def dateFormatChanged(self, widget): + """Signal handler for the "changed" signal for the dateFormat + GtkComboBox widget. Set the 'dateFormat' preference to the + new value. + + Arguments: + - widget: the component that generated the signal. + """ + + dateFormatCombo = widget.get_active() + if dateFormatCombo == DATE_FORMAT_LOCALE: + newFormat = messages.DATE_FORMAT_LOCALE + elif dateFormatCombo == DATE_FORMAT_NUMBERS_DM: + newFormat = messages.DATE_FORMAT_NUMBERS_DM + elif dateFormatCombo == DATE_FORMAT_NUMBERS_MD: + newFormat = messages.DATE_FORMAT_NUMBERS_MD + elif dateFormatCombo == DATE_FORMAT_NUMBERS_DMY: + newFormat = messages.DATE_FORMAT_NUMBERS_DMY + elif dateFormatCombo == DATE_FORMAT_NUMBERS_MDY: + newFormat = messages.DATE_FORMAT_NUMBERS_MDY + elif dateFormatCombo == DATE_FORMAT_NUMBERS_YMD: + newFormat = messages.DATE_FORMAT_NUMBERS_YMD + elif dateFormatCombo == DATE_FORMAT_FULL_DM: + newFormat = messages.DATE_FORMAT_FULL_DM + elif dateFormatCombo == DATE_FORMAT_FULL_MD: + newFormat = messages.DATE_FORMAT_FULL_MD + elif dateFormatCombo == DATE_FORMAT_FULL_DMY: + newFormat = messages.DATE_FORMAT_FULL_DMY + elif dateFormatCombo == DATE_FORMAT_FULL_MDY: + newFormat = messages.DATE_FORMAT_FULL_MDY + elif dateFormatCombo == DATE_FORMAT_FULL_YMD: + newFormat = messages.DATE_FORMAT_FULL_YMD + elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_DM: + newFormat = messages.DATE_FORMAT_ABBREVIATED_DM + elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_MD: + newFormat = messages.DATE_FORMAT_ABBREVIATED_MD + elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_DMY: + newFormat = messages.DATE_FORMAT_ABBREVIATED_DMY + elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_MDY: + newFormat = messages.DATE_FORMAT_ABBREVIATED_MDY + elif dateFormatCombo == DATE_FORMAT_ABBREVIATED_YMD: + newFormat = messages.DATE_FORMAT_ABBREVIATED_YMD + self.prefsDict["presentDateFormat"] = newFormat + + def timeFormatChanged(self, widget): + """Signal handler for the "changed" signal for the timeFormat + GtkComboBox widget. Set the 'timeFormat' preference to the + new value. + + Arguments: + - widget: the component that generated the signal. + """ + + timeFormatCombo = widget.get_active() + if timeFormatCombo == TIME_FORMAT_LOCALE: + newFormat = messages.TIME_FORMAT_LOCALE + elif timeFormatCombo == TIME_FORMAT_12_HM: + newFormat = messages.TIME_FORMAT_12_HM + elif timeFormatCombo == TIME_FORMAT_12_HMS: + newFormat = messages.TIME_FORMAT_12_HMS + elif timeFormatCombo == TIME_FORMAT_24_HMS: + newFormat = messages.TIME_FORMAT_24_HMS + elif timeFormatCombo == TIME_FORMAT_24_HMS_WITH_WORDS: + newFormat = messages.TIME_FORMAT_24_HMS_WITH_WORDS + elif timeFormatCombo == TIME_FORMAT_24_HM: + newFormat = messages.TIME_FORMAT_24_HM + elif timeFormatCombo == TIME_FORMAT_24_HM_WITH_WORDS: + newFormat = messages.TIME_FORMAT_24_HM_WITH_WORDS + self.prefsDict["presentTimeFormat"] = newFormat + + def speechVerbosityChanged(self, widget): + """Signal handler for the "toggled" signal for the speechBriefButton, + or speechVerboseButton GtkRadioButton widgets. The user has + toggled the speech verbosity level value. If this signal was + generated as the result of a radio button getting selected + (as opposed to a radio button losing the selection), set the + 'speechVerbosityLevel' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.VERBOSITY_LEVEL_BRIEF: + self.prefsDict["speechVerbosityLevel"] = \ + settings.VERBOSITY_LEVEL_BRIEF + else: + self.prefsDict["speechVerbosityLevel"] = \ + settings.VERBOSITY_LEVEL_VERBOSE + + def progressBarUpdateIntervalValueChanged(self, widget): + """Signal handler for the "value_changed" signal for the + progressBarUpdateIntervalSpinButton GtkSpinButton widget. + + Arguments: + - widget: the component that generated the signal. + """ + + self.prefsDict["progressBarUpdateInterval"] = widget.get_value_as_int() + + def brailleFlashTimeValueChanged(self, widget): + self.prefsDict["brailleFlashTime"] = widget.get_value_as_int() * 1000 + + def abbrevRolenamesChecked(self, widget): + """Signal handler for the "toggled" signal for the abbrevRolenames + GtkCheckButton widget. The user has [un]checked the 'Abbreviated + Rolenames' checkbox. Set the 'brailleRolenameStyle' preference + to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + self.prefsDict["brailleRolenameStyle"] = \ + settings.BRAILLE_ROLENAME_STYLE_SHORT + else: + self.prefsDict["brailleRolenameStyle"] = \ + settings.BRAILLE_ROLENAME_STYLE_LONG + + def brailleVerbosityChanged(self, widget): + """Signal handler for the "toggled" signal for the brailleBriefButton, + or brailleVerboseButton GtkRadioButton widgets. The user has + toggled the braille verbosity level value. If this signal was + generated as the result of a radio button getting selected + (as opposed to a radio button losing the selection), set the + 'brailleVerbosityLevel' preference to the new value. + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.VERBOSITY_LEVEL_BRIEF: + self.prefsDict["brailleVerbosityLevel"] = \ + settings.VERBOSITY_LEVEL_BRIEF + else: + self.prefsDict["brailleVerbosityLevel"] = \ + settings.VERBOSITY_LEVEL_VERBOSE + + def keyModifiedToggle(self, cell, path, model, col): + """When the user changes a checkbox field (boolean field)""" + + model[path][col] = not model[path][col] + return + + def editingKey(self, cell, editable, path, treeModel): + """Starts user input of a Key for a selected key binding""" + + self._presentMessage(messages.KB_ENTER_NEW_KEY) + cthulhu_state.capturingKeys = True + editable.connect('key-press-event', self.kbKeyPressed) + return + + def editingCanceledKey(self, editable): + """Stops user input of a Key for a selected key binding""" + + cthulhu_state.capturingKeys = False + self._capturedKey = [] + return + + def _processKeyCaptured(self, keyPressedEvent): + """Called when a new key event arrives and we are capturing keys. + (used for key bindings redefinition) + """ + + # We want the keyname rather than the printable character. + # If it's not on the keypad, get the name of the unshifted + # character. (i.e. "1" instead of "!") + # + keycode = keyPressedEvent.hardware_keycode + keymap = Gdk.Keymap.get_default() + entries_for_keycode = keymap.get_entries_for_keycode(keycode) + entries = entries_for_keycode[-1] + eventString = Gdk.keyval_name(entries[0]) + eventState = keyPressedEvent.state + + cthulhuMods = settings.cthulhuModifierKeys + if eventString in cthulhuMods: + self._capturedKey = ['', keybindings.CTHULHU_MODIFIER_MASK, 0] + return False + + modifierKeys = ['Alt_L', 'Alt_R', 'Control_L', 'Control_R', + 'Shift_L', 'Shift_R', 'Meta_L', 'Meta_R', + 'Num_Lock', 'Caps_Lock', 'Shift_Lock'] + if eventString in modifierKeys: + return False + + eventState = eventState & Gtk.accelerator_get_default_mod_mask() + if not self._capturedKey \ + or eventString in ['Return', 'Escape']: + self._capturedKey = [eventString, eventState, 1] + return True + + string, modifiers, clickCount = self._capturedKey + isCthulhuModifier = modifiers & keybindings.CTHULHU_MODIFIER_MASK + if isCthulhuModifier: + eventState |= keybindings.CTHULHU_MODIFIER_MASK + self._capturedKey = [eventString, eventState, clickCount + 1] + + return True + + def kbKeyPressed(self, editable, event): + """Special handler for the key_pressed events when editing the + keybindings. This lets us control what gets inserted into the + entry. + """ + + keyProcessed = self._processKeyCaptured(event) + if not keyProcessed: + return True + + if not self._capturedKey: + return False + + keyName, modifiers, clickCount = self._capturedKey + if not keyName or keyName in ["Return", "Escape"]: + return False + + isCthulhuModifier = modifiers & keybindings.CTHULHU_MODIFIER_MASK + if keyName in ["Delete", "BackSpace"] and not isCthulhuModifier: + editable.set_text("") + self._presentMessage(messages.KB_DELETED) + self._capturedKey = [] + self.newBinding = None + return True + + self.newBinding = keybindings.KeyBinding(keyName, + keybindings.defaultModifierMask, + modifiers, + None, + clickCount) + modifierNames = keybindings.getModifierNames(modifiers) + clickCountString = self._clickCountToString(clickCount) + newString = modifierNames + keyName + clickCountString + description = self.pendingKeyBindings.get(newString) + + if description is None: + + def match(x): + return x.keysymstring == keyName and x.modifiers == modifiers \ + and x.click_count == clickCount and x.handler + + matches = list(filter(match, self.kbindings.keyBindings)) + if matches: + description = matches[0].handler.description + + if description: + msg = messages.KB_ALREADY_BOUND % description + delay = int(1000 * settings.doubleClickTimeout) + GLib.timeout_add(delay, self._presentMessage, msg) + else: + msg = messages.KB_CAPTURED % newString + editable.set_text(newString) + self._presentMessage(msg) + + return True + + def editedKey(self, cell, path, new_text, treeModel, + modMask, modUsed, key, click_count, text): + """The user changed the key for a Keybinding: update the model of + the treeview. + """ + + cthulhu_state.capturingKeys = False + self._capturedKey = [] + myiter = treeModel.get_iter_from_string(path) + try: + originalBinding = treeModel.get_value(myiter, text) + except Exception: + originalBinding = '' + modified = (originalBinding != new_text) + + try: + string = self.newBinding.keysymstring + mods = self.newBinding.modifiers + clickCount = self.newBinding.click_count + except Exception: + string = '' + mods = 0 + clickCount = 1 + + mods = mods & Gdk.ModifierType.MODIFIER_MASK + if mods & (1 << Atspi.ModifierType.SHIFTLOCK) \ + and mods & keybindings.CTHULHU_MODIFIER_MASK: + mods ^= (1 << Atspi.ModifierType.SHIFTLOCK) + + treeModel.set(myiter, + modMask, str(keybindings.defaultModifierMask), + modUsed, str(int(mods)), + key, string, + text, new_text, + click_count, str(clickCount), + MODIF, modified) + speech.stop() + if new_text: + message = messages.KB_CAPTURED_CONFIRMATION % new_text + description = treeModel.get_value(myiter, DESCRIP) + self.pendingKeyBindings[new_text] = description + else: + message = messages.KB_DELETED_CONFIRMATION + + if modified: + self._presentMessage(message) + self.pendingKeyBindings[originalBinding] = "" + + return + + def presentToolTipsChecked(self, widget): + """Signal handler for the "toggled" signal for the + presentToolTipsCheckButton GtkCheckButton widget. + The user has [un]checked the 'Present ToolTips' + checkbox. Set the 'presentToolTips' + preference to the new value if the user can present tooltips. + + Arguments: + - widget: the component that generated the signal. + """ + + self.prefsDict["presentToolTips"] = widget.get_active() + + def keyboardLayoutChanged(self, widget): + """Signal handler for the "toggled" signal for the generalDesktopButton, + or generalLaptopButton GtkRadioButton widgets. The user has + toggled the keyboard layout value. If this signal was + generated as the result of a radio button getting selected + (as opposed to a radio button losing the selection), set the + 'keyboardLayout' preference to the new value. Also set the + matching list of Cthulhu modifier keys + + Arguments: + - widget: the component that generated the signal. + """ + + if widget.get_active(): + if widget.get_label() == guilabels.KEYBOARD_LAYOUT_DESKTOP: + self.prefsDict["keyboardLayout"] = \ + settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP + self.prefsDict["cthulhuModifierKeys"] = \ + settings.DESKTOP_MODIFIER_KEYS + else: + self.prefsDict["keyboardLayout"] = \ + settings.GENERAL_KEYBOARD_LAYOUT_LAPTOP + self.prefsDict["cthulhuModifierKeys"] = \ + settings.LAPTOP_MODIFIER_KEYS + + def pronunciationAddButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + pronunciationAddButton GtkButton widget. The user has clicked + the Add button on the Pronunciation pane. A new row will be + added to the end of the pronunciation dictionary list. Both the + actual and replacement strings will initially be set to an empty + string. Focus will be moved to that row. + + Arguments: + - widget: the component that generated the signal. + """ + + model = self.pronunciationView.get_model() + thisIter = model.append() + model.set(thisIter, ACTUAL, "", REPLACEMENT, "") + path = model.get_path(thisIter) + col = self.pronunciationView.get_column(0) + self.pronunciationView.grab_focus() + self.pronunciationView.set_cursor(path, col, True) + + def pronunciationDeleteButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + pronunciationDeleteButton GtkButton widget. The user has clicked + the Delete button on the Pronunciation pane. The row in the + pronunciation dictionary list with focus will be deleted. + + Arguments: + - widget: the component that generated the signal. + """ + + model, oldIter = self.pronunciationView.get_selection().get_selected() + model.remove(oldIter) + + def textSelectAllButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textSelectAllButton GtkButton widget. The user has clicked + the Speak all button. Check all the text attributes and + then update the "enabledSpokenTextAttributes" and + "enabledBrailledTextAttributes" preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + attributes = _settingsManager.getSetting('allTextAttributes') + self._setSpokenTextAttributes( + self.getTextAttributesView, attributes, True) + self._setBrailledTextAttributes( + self.getTextAttributesView, attributes, True) + self._updateTextDictEntry() + + def textUnselectAllButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textUnselectAllButton GtkButton widget. The user has clicked + the Speak none button. Uncheck all the text attributes and + then update the "enabledSpokenTextAttributes" and + "enabledBrailledTextAttributes" preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + attributes = _settingsManager.getSetting('allTextAttributes') + self._setSpokenTextAttributes( + self.getTextAttributesView, attributes, False) + self._setBrailledTextAttributes( + self.getTextAttributesView, attributes, False) + self._updateTextDictEntry() + + def textResetButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textResetButton GtkButton widget. The user has clicked + the Reset button. Reset all the text attributes to their + initial state and then update the "enabledSpokenTextAttributes" + and "enabledBrailledTextAttributes" preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + attributes = _settingsManager.getSetting('allTextAttributes') + self._setSpokenTextAttributes( + self.getTextAttributesView, attributes, False) + self._setBrailledTextAttributes( + self.getTextAttributesView, attributes, False) + + attributes = _settingsManager.getSetting('enabledSpokenTextAttributes') + self._setSpokenTextAttributes( + self.getTextAttributesView, attributes, True) + + attributes = \ + _settingsManager.getSetting('enabledBrailledTextAttributes') + self._setBrailledTextAttributes( + self.getTextAttributesView, attributes, True) + + self._updateTextDictEntry() + + def textMoveToTopButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textMoveToTopButton GtkButton widget. The user has clicked + the Move to top button. Move the selected rows in the text + attribute view to the very top of the list and then update + the "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" + preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + textSelection = self.getTextAttributesView.get_selection() + [model, paths] = textSelection.get_selected_rows() + for path in paths: + thisIter = model.get_iter(path) + model.move_after(thisIter, None) + self._updateTextDictEntry() + + def textMoveUpOneButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textMoveUpOneButton GtkButton widget. The user has clicked + the Move up one button. Move the selected rows in the text + attribute view up one row in the list and then update the + "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" + preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + textSelection = self.getTextAttributesView.get_selection() + [model, paths] = textSelection.get_selected_rows() + for path in paths: + thisIter = model.get_iter(path) + indices = path.get_indices() + if indices[0]: + otherIter = model.iter_nth_child(None, indices[0]-1) + model.swap(thisIter, otherIter) + self._updateTextDictEntry() + + def textMoveDownOneButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textMoveDownOneButton GtkButton widget. The user has clicked + the Move down one button. Move the selected rows in the text + attribute view down one row in the list and then update the + "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" + preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + textSelection = self.getTextAttributesView.get_selection() + [model, paths] = textSelection.get_selected_rows() + noRows = model.iter_n_children(None) + for path in paths: + thisIter = model.get_iter(path) + indices = path.get_indices() + if indices[0] < noRows-1: + otherIter = model.iter_next(thisIter) + model.swap(thisIter, otherIter) + self._updateTextDictEntry() + + def textMoveToBottomButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the + textMoveToBottomButton GtkButton widget. The user has clicked + the Move to bottom button. Move the selected rows in the text + attribute view to the bottom of the list and then update the + "enabledSpokenTextAttributes" and "enabledBrailledTextAttributes" + preference strings. + + Arguments: + - widget: the component that generated the signal. + """ + + textSelection = self.getTextAttributesView.get_selection() + [model, paths] = textSelection.get_selected_rows() + for path in paths: + thisIter = model.get_iter(path) + model.move_before(thisIter, None) + self._updateTextDictEntry() + + def helpButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the helpButton + GtkButton widget. The user has clicked the Help button. + + Arguments: + - widget: the component that generated the signal. + """ + + self.script.learnModePresenter.show_help(page="preferences") + + def restoreSettings(self): + """Restore the settings we saved away when opening the preferences + dialog.""" + # Restore the default rate/pitch/gain, + # in case the user played with the sliders. + # + voices = _settingsManager.getSetting('voices') + defaultVoice = voices.get(settings.DEFAULT_VOICE) + if defaultVoice is not None: + defaultVoice[acss.ACSS.GAIN] = self.savedGain + defaultVoice[acss.ACSS.AVERAGE_PITCH] = self.savedPitch + defaultVoice[acss.ACSS.RATE] = self.savedRate + + def saveBasicSettings(self): + if not self._isInitialSetup: + self.restoreSettings() + + enable = self.get_widget("speechSupportCheckButton").get_active() + self.prefsDict["enableSpeech"] = enable + + if self.speechSystemsChoice: + self.prefsDict["speechServerFactory"] = \ + self.speechSystemsChoice.__name__ + + if self.speechServersChoice: + self.prefsDict["speechServerInfo"] = \ + self.speechServersChoice.getInfo() + + if self.defaultVoice is not None: + self.prefsDict["voices"] = { + settings.DEFAULT_VOICE: acss.ACSS(self.defaultVoice), + settings.UPPERCASE_VOICE: acss.ACSS(self.uppercaseVoice), + settings.HYPERLINK_VOICE: acss.ACSS(self.hyperlinkVoice), + settings.SYSTEM_VOICE: acss.ACSS(self.systemVoice), + } + + def applyButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the applyButton + GtkButton widget. The user has clicked the Apply button. + Write out the users preferences. If GNOME accessibility hadn't + previously been enabled, warn the user that they will need to + log out. Shut down any active speech servers that were started. + Reload the users preferences to get the new speech, braille and + key echo value to take effect. Do not dismiss the configuration + window. + + Arguments: + - widget: the component that generated the signal. + """ + + msg = "PREFERENCES DIALOG: Apply button clicked" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + self.saveBasicSettings() + activeProfile = self.getComboBoxList(self.profilesCombo) + startingProfile = self.getComboBoxList(self.startingProfileCombo) + + self.prefsDict['profile'] = activeProfile + self.prefsDict['activeProfile'] = activeProfile + self.prefsDict['startingProfile'] = startingProfile + _settingsManager.setStartingProfile(startingProfile) + + self.writeUserPreferences() + cthulhu.loadUserSettings(self.script) + braille.checkBrailleSetting() + self._initSpeechState() + self._populateKeyBindings() + self.__initProfileCombo() + + msg = "PREFERENCES DIALOG: Handling Apply button click complete" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + def cancelButtonClicked(self, widget): + """Signal handler for the "clicked" signal for the cancelButton + GtkButton widget. The user has clicked the Cancel button. + Don't write out the preferences. Destroy the configuration window. + + Arguments: + - widget: the component that generated the signal. + """ + + msg = "PREFERENCES DIALOG: Cancel button clicked" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + self.windowClosed(widget) + self.get_widget("cthulhuSetupWindow").destroy() + + msg = "PREFERENCES DIALOG: Handling Cancel button click complete" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + def okButtonClicked(self, widget=None): + """Signal handler for the "clicked" signal for the okButton + GtkButton widget. The user has clicked the OK button. + Write out the users preferences. If GNOME accessibility hadn't + previously been enabled, warn the user that they will need to + log out. Shut down any active speech servers that were started. + Reload the users preferences to get the new speech, braille and + key echo value to take effect. Hide the configuration window. + + Arguments: + - widget: the component that generated the signal. + """ + + msg = "PREFERENCES DIALOG: OK button clicked" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + self.applyButtonClicked(widget) + self._cleanupSpeechServers() + self.get_widget("cthulhuSetupWindow").destroy() + + msg = "PREFERENCES DIALOG: Handling OK button click complete" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + def windowClosed(self, widget): + """Signal handler for the "closed" signal for the cthulhuSetupWindow + GtkWindow widget. This is effectively the same as pressing the + cancel button, except the window is destroyed for us. + + Arguments: + - widget: the component that generated the signal. + """ + + msg = "PREFERENCES DIALOG: Window is being closed" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + self.suspendEvents() + + factory = _settingsManager.getSetting('speechServerFactory') + if factory: + self._setSpeechSystemsChoice(factory) + + server = _settingsManager.getSetting('speechServerInfo') + if server: + self._setSpeechServersChoice(server) + + self._cleanupSpeechServers() + self.restoreSettings() + + GObject.timeout_add(1000, self.resumeEvents) + + msg = "PREFERENCES DIALOG: Window closure complete" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + def windowDestroyed(self, widget): + """Signal handler for the "destroyed" signal for the cthulhuSetupWindow + GtkWindow widget. Reset cthulhu_state.cthulhuOS to None, so that the + GUI can be rebuilt from the GtkBuilder file the next time the user + wants to display the configuration GUI. + + Arguments: + - widget: the component that generated the signal. + """ + + msg = "PREFERENCES DIALOG: Window is being destroyed" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + self.keyBindView.set_model(None) + self.getTextAttributesView.set_model(None) + self.pronunciationView.set_model(None) + self.keyBindView.set_headers_visible(False) + self.getTextAttributesView.set_headers_visible(False) + self.pronunciationView.set_headers_visible(False) + self.keyBindView.hide() + self.getTextAttributesView.hide() + self.pronunciationView.hide() + cthulhu_state.cthulhuOS = None + + msg = "PREFERENCES DIALOG: Window destruction complete" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + def resumeEvents(self): + msg = "PREFERENCES DIALOG: Re-registering floody events." + debug.printMessage(debug.LEVEL_ALL, msg, True) + + manager = event_manager.getManager() + manager.registerListener("object:state-changed:showing") + manager.registerListener("object:children-changed:remove") + manager.registerListener("object:selection-changed") + manager.registerListener("object:property-change:accessible-name") + + def suspendEvents(self): + msg = "PREFERENCES DIALOG: Deregistering floody events." + debug.printMessage(debug.LEVEL_ALL, msg, True) + + manager = event_manager.getManager() + manager.deregisterListener("object:state-changed:showing") + manager.deregisterListener("object:children-changed:remove") + manager.deregisterListener("object:selection-changed") + manager.deregisterListener("object:property-change:accessible-name") + + def showProfileGUI(self, widget): + """Show profile Dialog to add a new one""" + + cthulhu_gui_profile.showProfileUI(self) + + def saveProfile(self, profileToSaveLabel): + """Creates a new profile based on the name profileToSaveLabel and + updates the Preferences dialog combo boxes accordingly.""" + + if not profileToSaveLabel: + return + profileToSave = profileToSaveLabel.replace(' ', '_').lower() + profile = [profileToSaveLabel, profileToSave] + + def saveActiveProfile(newProfile = True): + if newProfile: + activeProfileIter = self.profilesComboModel.append(profile) + self.profilesCombo.set_active_iter(activeProfileIter) + + self.prefsDict['profile'] = profile + self.prefsDict['activeProfile'] = profile + self.saveBasicSettings() + self.writeUserPreferences() + + availableProfiles = [p[1] for p in self.__getAvailableProfiles()] + if isinstance(profileToSave, str) \ + and profileToSave != '' \ + and profileToSave not in availableProfiles \ + and profileToSave != self._defaultProfile[1]: + saveActiveProfile() + else: + if profileToSave is not None: + message = guilabels.PROFILE_CONFLICT_MESSAGE % \ + f"{GLib.markup_escape_text(profileToSaveLabel)}" + dialog = Gtk.MessageDialog(None, + Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.YES_NO) + dialog.set_markup(f"{guilabels.PROFILE_CONFLICT_LABEL}") + dialog.format_secondary_markup(message) + dialog.set_title(guilabels.PROFILE_CONFLICT_TITLE) + response = dialog.run() + if response == Gtk.ResponseType.YES: + dialog.destroy() + saveActiveProfile(False) + else: + dialog.destroy() + + + def removeProfileButtonClicked(self, widget): + """Remove profile button clicked handler + + If we removed the last profile, a default one will automatically get + added back by the settings manager. + """ + + oldProfile = self.getComboBoxList(self.profilesCombo) + + message = guilabels.PROFILE_REMOVE_MESSAGE % \ + f"{GLib.markup_escape_text(oldProfile[0])}" + dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.YES_NO) + dialog.set_markup(f"{guilabels.PROFILE_REMOVE_LABEL}") + dialog.format_secondary_markup(message) + if dialog.run() == Gtk.ResponseType.YES: + # If we remove the currently used starting profile, fallback on + # the first listed profile, or the default one if there's + # nothing better + newStartingProfile = self.prefsDict.get('startingProfile') + if not newStartingProfile or newStartingProfile == oldProfile: + newStartingProfile = self._defaultProfile + for row in self.profilesComboModel: + rowProfile = row[:] + if rowProfile != oldProfile: + newStartingProfile = rowProfile + break + # Update the current profile to the active profile unless we're + # removing that one, in which case we use the new starting + # profile + newProfile = self.prefsDict.get('activeProfile') + if not newProfile or newProfile == oldProfile: + newProfile = newStartingProfile + + _settingsManager.removeProfile(oldProfile[1]) + self.loadProfile(newProfile) + + # Make sure nothing is referencing the removed profile anymore + startingProfile = self.prefsDict.get('startingProfile') + if not startingProfile or startingProfile == oldProfile: + self.prefsDict['startingProfile'] = newStartingProfile + _settingsManager.setStartingProfile(newStartingProfile) + self.writeUserPreferences() + + dialog.destroy() + + def loadProfileButtonClicked(self, widget): + """Load profile button clicked handler""" + + if self._isInitialSetup: + return + + dialog = Gtk.MessageDialog(None, + Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.YES_NO) + + dialog.set_markup(f"{guilabels.PROFILE_LOAD_LABEL}") + dialog.format_secondary_markup(guilabels.PROFILE_LOAD_MESSAGE) + response = dialog.run() + if response == Gtk.ResponseType.YES: + dialog.destroy() + self.loadSelectedProfile() + else: + dialog.destroy() + + def loadSelectedProfile(self): + """Load selected profile""" + + activeProfile = self.getComboBoxList(self.profilesCombo) + self.loadProfile(activeProfile) + + def loadProfile(self, profile): + """Load profile""" + + self.saveBasicSettings() + + self.prefsDict['activeProfile'] = profile + _settingsManager.setProfile(profile[1]) + self.prefsDict = _settingsManager.getGeneralSettings(profile[1]) + + cthulhu.loadUserSettings(skipReloadMessage=True) + + self._initGUIState() + + braille.checkBrailleSetting() + + self._initSpeechState() + + self._populateKeyBindings() + + self.__initProfileCombo() + + # AI Assistant signal handlers + + def enableAIToggled(self, widget): + """Enable AI Assistant checkbox toggled handler""" + enabled = widget.get_active() + self.prefsDict["aiAssistantEnabled"] = enabled + self._updateAIControlsState(enabled) + + def aiProviderChanged(self, widget): + """AI Provider combo box changed handler""" + providers = [settings.AI_PROVIDER_CLAUDE_CODE, settings.AI_PROVIDER_CLAUDE, + settings.AI_PROVIDER_CHATGPT, settings.AI_PROVIDER_GEMINI, settings.AI_PROVIDER_OLLAMA] + activeIndex = widget.get_active() + if 0 <= activeIndex < len(providers): + provider = providers[activeIndex] + self.prefsDict["aiProvider"] = provider + self._updateProviderControls(provider) + + def aiApiKeyChanged(self, widget): + """AI API key file entry changed handler""" + self.prefsDict["aiApiKeyFile"] = widget.get_text() + + def aiOllamaModelChanged(self, widget): + """AI Ollama model entry changed handler""" + self.prefsDict["aiOllamaModel"] = widget.get_text() + + def aiOllamaEndpointChanged(self, widget): + """AI Ollama endpoint entry changed handler""" + self.prefsDict["aiOllamaEndpoint"] = widget.get_text() + + def aiGetClaudeKeyClicked(self, widget): + """Get Claude API Key button clicked handler""" + import subprocess + import os + + try: + # Open browser to Claude API key page + subprocess.run(["xdg-open", "https://console.anthropic.com/"], check=True) + + # Show dialog with instructions + dialog = Gtk.MessageDialog( + parent=self, + flags=Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.OK, + message_format="Claude API Key Setup" + ) + dialog.format_secondary_text( + "Browser opened to get your Claude API key.\n\n" + "💡 TIP: Claude offers $5 free credit, then ~$20/month for Pro.\n" + "Ollama is also available as a free alternative.\n\n" + "Steps:\n" + "1. Sign up or log in to your Anthropic account\n" + "2. Go to 'API Keys' in Account Settings\n" + "3. Click 'Create Key' and copy the API key\n" + "4. Click OK below when you have your key ready\n" + "5. Paste the API key when prompted" + ) + dialog.run() + dialog.destroy() + + # Show API key input dialog + key_dialog = Gtk.MessageDialog( + parent=self, + flags=Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.QUESTION, + buttons=Gtk.ButtonsType.OK_CANCEL, + message_format="Enter Claude API Key" + ) + key_dialog.format_secondary_text("Paste your Claude API key (starts with 'sk-ant-'):") + + # Add text entry to dialog + entry = Gtk.Entry() + entry.set_placeholder_text("sk-ant-your-api-key-here...") + entry.set_visibility(False) # Hide key for security + entry.set_width_chars(50) + key_dialog.get_content_area().pack_start(entry, False, False, 0) + entry.show() + + response = key_dialog.run() + api_key = entry.get_text().strip() + key_dialog.destroy() + + if response == Gtk.ResponseType.OK and api_key: + # Save API key to file + config_dir = os.path.expanduser("~/.local/share/cthulhu") + os.makedirs(config_dir, exist_ok=True) + api_key_file = os.path.join(config_dir, "claude-api-key") + + with open(api_key_file, 'w') as f: + f.write(api_key) + os.chmod(api_key_file, 0o600) # Secure file permissions + + # Update GUI + self.get_widget("aiApiKeyEntry").set_text(api_key_file) + self.prefsDict["aiApiKeyFile"] = api_key_file + + # Success message + success_dialog = Gtk.MessageDialog( + parent=self, + flags=Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.OK, + message_format="API Key Saved Successfully" + ) + success_dialog.format_secondary_text(f"Claude API key saved to:\n{api_key_file}") + success_dialog.run() + success_dialog.destroy() + + except Exception as e: + # Error dialog + error_dialog = Gtk.MessageDialog( + parent=self, + flags=Gtk.DialogFlags.MODAL, + type=Gtk.MessageType.ERROR, + buttons=Gtk.ButtonsType.OK, + message_format="Error Setting Up API Key" + ) + error_dialog.format_secondary_text(f"Failed to open browser or save API key:\n{str(e)}") + error_dialog.run() + error_dialog.destroy() + + def aiApiKeyBrowseClicked(self, widget): + """AI API key browse button clicked handler""" + dialog = Gtk.FileChooserDialog( + title="Select API Key File", + parent=self, + action=Gtk.FileChooserAction.OPEN + ) + dialog.add_buttons( + Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, Gtk.ResponseType.OK + ) + + response = dialog.run() + if response == Gtk.ResponseType.OK: + filename = dialog.get_filename() + self.aiApiKeyEntry.set_text(filename) + self.prefsDict["aiApiKeyFile"] = filename + + dialog.destroy() + + def aiConfirmationToggled(self, widget): + """AI confirmation required checkbox toggled handler""" + self.prefsDict["aiConfirmationRequired"] = widget.get_active() + + def aiScreenshotQualityChanged(self, widget): + """AI screenshot quality combo box changed handler""" + qualities = [settings.AI_SCREENSHOT_QUALITY_LOW, + settings.AI_SCREENSHOT_QUALITY_MEDIUM, + settings.AI_SCREENSHOT_QUALITY_HIGH] + activeIndex = widget.get_active() + if 0 <= activeIndex < len(qualities): + self.prefsDict["aiScreenshotQuality"] = qualities[activeIndex] + + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_profile.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_profile.py new file mode 100644 index 0000000..325759f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_gui_profile.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Displays the Save Profile As dialog.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios." +__license__ = "LGPL" + +import locale +import sys +from gi.repository import Gtk + +from . import guilabels +from . import cthulhu_state + +OS = None +newProfile = None + +class CthulhuProfileGUI(Gtk.Dialog): + + def __init__(self): + """Initialize the Cthulhu profile configuration GUI.""" + + Gtk.Dialog.__init__(self) + self.set_title(guilabels.PROFILE_SAVE_AS_TITLE) + self.set_has_resize_grip(False) + + self.add_button('gtk-cancel', Gtk.ResponseType.CANCEL) + self.add_button('gtk-save', Gtk.ResponseType.ACCEPT) + + grid = Gtk.Grid() + grid.set_property('margin', 12) + grid.set_row_spacing(10) + grid.set_column_spacing(10) + + # Right now the content area is a GtkBox. We'll need to update + # this once GtkBox is fully deprecated. + contentArea = self.get_content_area() + contentArea.pack_start(grid, True, True, 0) + + self.profileEntry = Gtk.Entry() + self.profileEntry.set_property('hexpand', True) + self.profileEntry.set_activates_default(True) + grid.attach(self.profileEntry, 1, 0, 1, 1) + + label = Gtk.Label(guilabels.PROFILE_NAME_LABEL) + label.set_use_underline(True) + label.set_mnemonic_widget(self.profileEntry) + grid.attach(label, 0, 0, 1, 1) + + defaultButton = self.get_widget_for_response(Gtk.ResponseType.ACCEPT) + defaultButton.set_property('can-default', True) + defaultButton.set_property('has-default', True) + + self.connect('response', self.onResponse) + self.connect('destroy', self.onDestroy) + + self.searchString = None + self.profileString = None + self.prefsDialog = None + + def init(self): + self.profileString = '' + + def showGUI(self, prefsDialog): + """Show the Save Profile As dialog.""" + + self.show_all() + self.prefsDialog = prefsDialog + self.profileEntry.set_text(self.profileString) + + ts = cthulhu_state.lastInputEvent.timestamp + if ts == 0: + ts = Gtk.get_current_event_time() + self.present_with_time(ts) + + def onResponse(self, widget, response): + """Signal handler for the responses emitted by the dialog.""" + + if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]: + self.hide() + return + + if response == Gtk.ResponseType.ACCEPT: + global newProfile + + newProfile = self.profileEntry.get_text() + if newProfile: + self.destroy() + if self.prefsDialog: + self.prefsDialog.saveProfile(newProfile) + + def onDestroy(self, widget): + """Signal handler for the 'destroy' signal of the dialog.""" + + global OS + + OS = None + +def showProfileUI(prefsDialog=None): + global OS + global newProfile + + newProfile = None + + if not OS: + OS = CthulhuProfileGUI() + OS.init() + + OS.showGUI(prefsDialog) + +def main(): + locale.setlocale(locale.LC_ALL, '') + + showProfileUI() + + Gtk.main() + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_i18n.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_i18n.py new file mode 100644 index 0000000..8ac203e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_i18n.py @@ -0,0 +1,91 @@ +# Cthulhu +# +# Copyright 2004-2008 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. + +"""Provides i18n support for cthulhu using the gettext module. Tells +gettext where to find localized strings and creates an alias, _, that +maps to the gettext.gettext function. This function will accept a +string and return a localized string for that string. +""" + +import gettext +import importlib +import os +import sys + +# Alias gettext.gettext to _ and gettext.ngettext to ngettext +# +_ = gettext.gettext +ngettext = gettext.ngettext +cgettext = gettext.gettext + +# Tell gettext where to find localized strings. +# +localedir = "share/locale".replace('${prefix}', '/usr') +gettext.bindtextdomain ("cthulhu", localedir) +gettext.textdomain("cthulhu") + +######################################################################## +# # +# Utility methods to facilitate easier translation # +# # +######################################################################## + +def C_(ctx, s): + """Provide qualified translatable strings via context.""" + translated = cgettext('%s\x04%s' % (ctx, s)) + if '\x04' in translated: + # no translation found, return input string + return s + return translated + +def setModuleLocale(moduleName, newLocale=None): + global _, ngettext, cgettext + + try: + translation = gettext.translation('cthulhu', localedir, languages=[newLocale]) + _ = translation.gettext + ngettext = translation.ngettext + cgettext = translation.gettext + except: + _ = gettext.gettext + ngettext = gettext.ngettext + cgettext = gettext.gettext + module = sys.modules.get(moduleName) + if module: + importlib.reload(module) + +def setLocaleForMessages(newLocale=None): + modules = ['cthulhu.tutorialgenerator', 'cthulhu.messages'] + for module in modules: + setModuleLocale(module, newLocale) + +def setLocaleForNames(newLocale=None): + modules = ['cthulhu.chnames', 'cthulhu.keynames', 'cthulhu.phonnames', + 'cthulhu.text_attribute_names', 'cthulhu.object_properties', + 'cthulhu.cmdnames', 'cthulhu.keybindings', 'cthulhu.colornames', + 'cthulhu.mathsymbols'] + for module in modules: + setModuleLocale(module, newLocale) + +def setLocaleForGUI(newLocale=None): + modules = ['cthulhu.cthulhu_gtkbuilder', + 'cthulhu.guilabels', + 'cthulhu.brltablenames'] + for module in modules: + setModuleLocale(module, newLocale) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_platform.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_platform.py new file mode 100644 index 0000000..54def36 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_platform.py @@ -0,0 +1,53 @@ +# Cthulhu +# +# Copyright 2006-2008 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. + +from cthulhu import cthulhuVersion + +"""Holds platform-specific settings. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +# $CTHULHU_VERSION +# +version = f"Cthulhu screen reader version {cthulhuVersion.version}-{cthulhuVersion.codeName}" + +# The revision if built from git; otherwise an empty string +# +revision = "5cbe626" + +# "--prefix" parameter used when configuring the build. +# +prefix = "/usr" + +# The package name (should be "cthulhu"). +# +package = "cthulhu" + +# The location of the data directory (usually "share"). +# +datadir = "share".replace('${prefix}', '/usr') + +# The directory where we could find liblouis translation tables. +# +tablesdir = "/usr/share/liblouis/tables" diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_state.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_state.py new file mode 100644 index 0000000..a4b547e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/cthulhu_state.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Holds state that is shared among many modules. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010 Joanmarie Diggs, Mesar Hameed." +__license__ = "LGPL" + +# NOTE: resist the temptation to do any imports here. They can +# easily cause circular imports. +# + +# The Accessible that has visual focus. +# +locusOfFocus = None + +# The currently active window. +# +activeWindow = None + +# The currently active script. +# +activeScript = None + +# The currently active mode (focus, say all, flat review, etc.) and obj +activeMode = None +objOfInterest = None + +# Used to capture keys to redefine key bindings by the user. +# +capturingKeys = False + +# The last non-modifier key event received. +# +lastNonModifierKeyEvent = None + +# The InputEvent instance representing the last input event. This is +# set each time a mouse, keyboard or braille event is received. +# +lastInputEvent = None + +# Used to determine if the user wishes Cthulhu to pass the next command +# along to the current application rather than consuming it. +# +bypassNextCommand = False + +# The last searchQuery +# +searchQuery = None + +# Handle to the Cthulhu Preferences Glade GUI object. +# +cthulhuOS = None + +# Set to True if the last key opened the preferences dialog +# +openingDialog = False + +# The AT-SPI device (needed for key grabs). Will be set to None if AT-SPI +# is too old to support the new device API. +# +device = None diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/date_and_time_presenter.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/date_and_time_presenter.py new file mode 100644 index 0000000..b8df145 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/date_and_time_presenter.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for date and time presentation""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2016-2023 Igalia, S.L." +__license__ = "LGPL" + +import time + +from . import cmdnames +from . import input_event +from . import keybindings +from . import settings_manager + +_settingsManager = settings_manager.getManager() + +class DateAndTimePresenter: + """Provides commands to present the date and time.""" + + def __init__(self): + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + + def get_bindings(self): + """Returns the date-and-time-presenter keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the date-and-time-presenter handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the date-and-time-presenter input event handlers.""" + + handlers = {} + + handlers["presentTimeHandler"] = \ + input_event.InputEventHandler( + self.present_time, + cmdnames.PRESENT_CURRENT_TIME) + + handlers["presentDateHandler"] = \ + input_event.InputEventHandler( + self.present_date, + cmdnames.PRESENT_CURRENT_DATE) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the date-and-time-presenter key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "t", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("presentTimeHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "t", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("presentDateHandler"), + 2)) + + return bindings + + def present_time(self, script, event=None): + """Presents the current time.""" + + format = _settingsManager.getSetting('presentTimeFormat') + script.presentMessage(time.strftime(format, time.localtime())) + return True + + def present_date(self, script, event=None): + """Presents the current date.""" + + format = _settingsManager.getSetting('presentDateFormat') + script.presentMessage(time.strftime(format, time.localtime())) + return True + + +_presenter = None +def getPresenter(): + global _presenter + if _presenter is None: + _presenter = DateAndTimePresenter() + return _presenter diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dbus_service.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dbus_service.py new file mode 100644 index 0000000..a32dedc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dbus_service.py @@ -0,0 +1,862 @@ +# Cthulhu +# +# Copyright 2025 Stormux +# Copyright 2025 Valve Corporation +# Author: Joanmarie Diggs +# +# 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. + +"""Provides a D-Bus interface for remotely controlling Cthulhu.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2025 Stormux " +__license__ = "LGPL" + +import enum +import inspect +from typing import Callable + +try: + from dasbus.connection import SessionMessageBus + from dasbus.error import DBusError + from dasbus.loop import EventLoop + from dasbus.server.interface import dbus_interface + from dasbus.server.publishable import Publishable + _dasbus_available = True +except ImportError: + _dasbus_available = False + +from gi.repository import GLib + +from . import debug +from . import cthulhu_platform # pylint: disable=no-name-in-module +from . import script_manager +from . import cthulhu_state + +# Lazy import to avoid circular dependency +def _get_input_event(): + from . import input_event + return input_event + +class HandlerType(enum.Enum): + """Enumeration of handler types for D-Bus methods.""" + + COMMAND = enum.auto() + PARAMETERIZED_COMMAND = enum.auto() + GETTER = enum.auto() + SETTER = enum.auto() + +def command(func): + """Decorator to mark a method as a D-Bus command using its docstring. + + Usage: + @command + def toggle_speech(self, script=None, event=None): + '''Toggles speech on and off.''' + # method implementation + """ + description = func.__doc__ or f"D-Bus command: {func.__name__}" + func.dbus_command_description = description + return func + +def getter(func): + """Decorator to mark a method as a D-Bus getter using its docstring. + + Usage: + @getter + def get_rate(self): + '''Returns the current speech rate.''' + # method implementation + """ + description = func.__doc__ or f"D-Bus getter: {func.__name__}" + func.dbus_getter_description = description + return func + +def parameterized_command(func): + """Decorator to mark a method as a D-Bus parameterized command using its docstring. + + Usage: + @parameterized_command + def get_voices_for_language( + self, + language, + variant='', + script=None, + event=None, + notify_user=False + ): + '''Returns a list of available voices for the specified language.''' + # method implementation + """ + description = func.__doc__ or f"D-Bus parameterized command: {func.__name__}" + func.dbus_parameterized_command_description = description + return func + +def setter(func): + """Decorator to mark a method as a D-Bus setter using its docstring. + + Usage: + @setter + def set_rate(self, value): + '''Sets the current speech rate.''' + # method implementation + """ + description = func.__doc__ or f"D-Bus setter: {func.__name__}" + func.dbus_setter_description = description + return func + +def _extract_function_parameters(func: Callable) -> list[tuple[str, str]]: + """Extract parameter names and types from a function signature.""" + + sig = inspect.signature(func) + parameters = [] + + skip_params = {"self", "script", "event"} + for param_name, param in sig.parameters.items(): + if param_name in skip_params: + continue + + if param.annotation != inspect.Parameter.empty: + if hasattr(param.annotation, "__name__"): + type_str = param.annotation.__name__ + else: + type_str = str(param.annotation).replace("typing.", "") + else: + type_str = "Any" + parameters.append((param_name, type_str)) + + return parameters + + +class _HandlerInfo: + """Stores processed information about a function exposed via D-Bus.""" + + def __init__( + self, + python_function_name: str, + description: str, + action: Callable[..., bool], + handler_type: 'HandlerType' = HandlerType.COMMAND, + parameters: list[tuple[str, str]] | None = None + ): + self.python_function_name: str = python_function_name + self.description: str = description + self.action: Callable[..., bool] = action + self.handler_type: HandlerType = handler_type + self.parameters: list[tuple[str, str]] = parameters or [] + + +if _dasbus_available: + @dbus_interface("org.stormux.Cthulhu.Module") + class CthulhuModuleDBusInterface(Publishable): + """A D-Bus interface representing a specific Cthulhu module (e.g., a manager).""" + + def __init__(self, + module_name: str, + handlers_info: list[_HandlerInfo]): + super().__init__() + self._module_name = module_name + self._commands: dict[str, _HandlerInfo] = {} + self._parameterized_commands: dict[str, _HandlerInfo] = {} + self._getters: dict[str, _HandlerInfo] = {} + self._setters: dict[str, _HandlerInfo] = {} + + for info in handlers_info: + handler_type = getattr(info, "handler_type", HandlerType.COMMAND) + normalized_name = self._normalize_handler_name(info.python_function_name, handler_type) + if handler_type == HandlerType.GETTER: + self._getters[normalized_name] = info + elif handler_type == HandlerType.SETTER: + self._setters[normalized_name] = info + elif handler_type == HandlerType.PARAMETERIZED_COMMAND: + self._parameterized_commands[normalized_name] = info + else: + self._commands[normalized_name] = info + + msg = ( + f"DBUS SERVICE: CthulhuModuleDBusInterface for {module_name} initialized " + f"with {len(self._commands)} command(s), " + f"{len(self._parameterized_commands)} parameterized command(s), " + f"{len(self._getters)} getter(s), {len(self._setters)} setter(s)." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def ExecuteRuntimeGetter(self, getter_name: str) -> GLib.Variant: # pylint: disable=invalid-name + """Executes the named getter returning the value as a GLib.Variant for D-Bus marshalling.""" + + handler_info = self._getters.get(getter_name) + if not handler_info: + msg = f"DBUS SERVICE: Unknown getter '{getter_name}' for '{self._module_name}'." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return GLib.Variant("v", GLib.Variant("s", "")) + + result = handler_info.action() + msg = f"DBUS SERVICE: Getter '{getter_name}' returned: {result}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return self._to_variant(result) + + def ExecuteRuntimeSetter(self, setter_name: str, value: GLib.Variant) -> bool: # pylint: disable=invalid-name + """Executes the named setter, returning True if succeeded.""" + + handler_info = self._setters.get(setter_name) + if handler_info is None: + msg = f"DBUS SERVICE: Unknown setter '{setter_name}' for '{self._module_name}'." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + unpacked = value.unpack() + result = handler_info.action(unpacked) + msg = f"DBUS SERVICE: Setter '{setter_name}' with value '{unpacked}' returned: {result}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return result + + def ListCommands(self) -> list[tuple[str, str]]: # pylint: disable=invalid-name + """Returns a list of (command_name, description) for this module (commands only).""" + + command_list = [] + for camel_case_name, info in self._commands.items(): + command_list.append((camel_case_name, info.description)) + return command_list + + def ListParameterizedCommands( # pylint: disable=invalid-name + self, + ) -> list[tuple[str, str, list[tuple[str, str]]]]: + """Returns a list of (command_name, description, parameters) for this module.""" + + command_list = [] + for camel_case_name, info in self._parameterized_commands.items(): + command_list.append((camel_case_name, info.description, info.parameters)) + return command_list + + def ListRuntimeGetters(self) -> list[tuple[str, str]]: # pylint: disable=invalid-name + """Returns a list of (getter_name, description) for this module.""" + + getter_list = [] + for camel_case_name, info in self._getters.items(): + getter_list.append((camel_case_name, info.description)) + return getter_list + + def ListRuntimeSetters(self) -> list[tuple[str, str]]: # pylint: disable=invalid-name + """Returns a list of (setter_name, description) for this module.""" + + setter_list = [] + for camel_case_name, info in self._setters.items(): + setter_list.append((camel_case_name, info.description)) + return setter_list + + def ExecuteCommand(self, command_name: str, notify_user: bool) -> bool: # pylint: disable=invalid-name + """Executes the named command and returns True if the command succeeded.""" + + if command_name not in self._commands: + msg = f"DBUS SERVICE: Unknown command '{command_name}' for '{self._module_name}'." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + handler_info = self._commands[command_name] + result = handler_info.action(notify_user) + msg = ( + f"DBUS SERVICE: '{command_name}' in '{self._module_name}' executed. " + f"Result: {result}, notify_user: {notify_user}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return result + + def ExecuteParameterizedCommand( # pylint: disable=invalid-name + self, + command_name: str, + parameters: dict[str, GLib.Variant], + notify_user: bool + ) -> GLib.Variant: + """Executes the named command with parameters and returns the result.""" + + handler_info = self._parameterized_commands.get(command_name) + if not handler_info: + msg = ( + f"DBUS SERVICE: Unknown parameterized command '{command_name}' for " + f"'{self._module_name}'." + ) + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return GLib.Variant("b", False) + + kwargs = {name: variant.unpack() for name, variant in parameters.items()} + kwargs["notify_user"] = notify_user + result = handler_info.action(**kwargs) + msg = f"DBUS SERVICE: Parameterized '{command_name}' in '{self._module_name}' executed." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return self._to_variant(result) + + def for_publication(self): + """Returns the D-Bus interface XML for publication.""" + + return self.__dbus_xml__ # pylint: disable=no-member + + + @staticmethod + def _normalize_handler_name( + function_name: str, + handler_type: HandlerType = HandlerType.COMMAND + ) -> str: + """Normalizes a Python function name for D-Bus exposure (getter/setter/command).""" + + # Only strip prefixes for getters and setters, not for commands + if handler_type in (HandlerType.GETTER, HandlerType.SETTER): + if function_name.startswith("get_") or function_name.startswith("set_"): + function_name = function_name[4:] + return "".join(word.capitalize() for word in function_name.split("_")) + + @staticmethod + def _to_variant(result): + """Converts a Python value to a correctly-typed GLib.Variant for D-Bus marshalling.""" + + if isinstance(result, bool): + return GLib.Variant("b", result) + if isinstance(result, int): + return GLib.Variant("i", result) + if isinstance(result, float): + return GLib.Variant("d", result) + if isinstance(result, str): + return GLib.Variant("s", result) + if isinstance(result, dict): + return GLib.Variant( + "a{sv}", {str(k): GLib.Variant("v", v) for k, v in result.items()}) + if isinstance(result, (list, tuple)): + if all(isinstance(x, str) for x in result): + return GLib.Variant("as", list(result)) + if all(isinstance(x, bool) for x in result): + return GLib.Variant("ab", list(result)) + if all(isinstance(x, int) for x in result): + return GLib.Variant("ax", list(result)) + if all(isinstance(x, (list, tuple)) for x in result): + if not result: + return GLib.Variant("av", []) + first_len = len(result[0]) + converted = [tuple(str(item or "") for item in x) for x in result] + signature = "(" + "s" * first_len + ")" + return GLib.Variant(f"a{signature}", converted) + return GLib.Variant("av", [GLib.Variant("v", x) for x in result]) + if result is None: + return GLib.Variant("v", GLib.Variant("s", "")) + return GLib.Variant("s", str(result)) + + + @dbus_interface("org.stormux.Cthulhu.Service") + class CthulhuDBusServiceInterface(Publishable): + """Internal D-Bus service object that handles D-Bus specifics.""" + + def __init__(self) -> None: + super().__init__() + self._registered_modules: set[str] = set() + msg = "DBUS SERVICE: CthulhuDBusServiceInterface initialized." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def for_publication(self): + """Returns the D-Bus interface XML for publication.""" + + return self.__dbus_xml__ # pylint: disable=no-member + + def add_module_interface( + self, + module_name: str, + handlers_info: list[_HandlerInfo], + bus: SessionMessageBus, + object_path_base: str + ) -> None: + """Creates and prepares a D-Bus interface for a Cthulhu module.""" + + object_path = f"{object_path_base}/{module_name}" + if module_name in self._registered_modules: + msg = f"DBUS SERVICE: Interface {module_name} already registered. Replacing." + debug.printMessage(debug.LEVEL_INFO, msg, True) + try: + bus.unpublish_object(object_path) + except DBusError as e: + msg = f"DBUS SERVICE: Error unpublishing old interface for {module_name}: {e}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._registered_modules.discard(module_name) + try: + module_iface = CthulhuModuleDBusInterface(module_name, handlers_info) + bus.publish_object(object_path, module_iface) + self._registered_modules.add(module_name) + msg = f"DBUS SERVICE: Successfully published {module_name} at {object_path}." + debug.printMessage(debug.LEVEL_INFO, msg, True) + except DBusError as e: + msg = ( + f"DBUS SERVICE: Failed to create or publish D-Bus interface for " + f"module {module_name} at {object_path}: {e}" + ) + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + + def remove_module_interface( + self, + module_name: str, + bus: SessionMessageBus, + object_path_base: str + ) -> bool: + """Removes and unpublishes a D-Bus interface for a Cthulhu module.""" + + if module_name not in self._registered_modules: + msg = f"DBUS SERVICE: Module {module_name} is not registered." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + object_path = f"{object_path_base}/{module_name}" + try: + bus.unpublish_object(object_path) + self._registered_modules.discard(module_name) + msg = f"DBUS SERVICE: Successfully removed {module_name} from {object_path}." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + except DBusError as e: + msg = f"DBUS SERVICE: Error removing interface for {module_name}: {e}" + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + def ListModules(self) -> list[str]: # pylint: disable=invalid-name + """Returns a list of registered module names.""" + + return list(self._registered_modules) + + def ListCommands(self) -> list[tuple[str, str]]: # pylint: disable=invalid-name + """Returns available commands on the main service interface.""" + + commands = [] + for attr_name in dir(self): + if not attr_name.startswith('_') and attr_name[0].isupper(): + attr = getattr(self, attr_name) + if callable(attr) and hasattr(attr, '__doc__'): + description = (attr.__doc__.strip() if attr.__doc__ + else f"Service command: {attr_name}") + commands.append((attr_name, description)) + + return sorted(commands) + + def ShowPreferences(self) -> bool: # pylint: disable=invalid-name + """Shows Cthulhu's preferences GUI.""" + + msg = "DBUS SERVICE: ShowPreferences called." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + manager = script_manager.getManager() + script = cthulhu_state.activeScript or manager.getDefaultScript() + if script is None: + msg = "DBUS SERVICE: No script available" + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + script.showPreferencesGUI() + return True + + def PresentMessage(self, message: str) -> bool: # pylint: disable=invalid-name + """Presents message to the user.""" + + msg = f"DBUS SERVICE: PresentMessage called with: '{message}'" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + manager = script_manager.getManager() + script = cthulhu_state.activeScript or script_manager.getManager().getDefaultScript() + if script is None: + msg = "DBUS SERVICE: No script available" + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + script.presentMessage(message) + return True + + def GetVersion(self) -> str: # pylint: disable=invalid-name + """Returns Cthulhu's version and revision if available.""" + + result = cthulhu_platform.version + if cthulhu_platform.revision: + result += f" (rev {cthulhu_platform.revision})" + + msg = f"DBUS SERVICE: GetVersion called, returning: {result}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return result + + def Quit(self) -> bool: # pylint: disable=invalid-name + """Quits Cthulhu. Returns True if the quit request was accepted.""" + + msg = "DBUS SERVICE: Quit called." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + from . import cthulhu # pylint: disable=import-outside-toplevel + + # cthulhu.shutdown() shuts down the dbus service, so send the response immediately and then + # do the actual shutdown after a brief delay. + def _delayed_shutdown(): + cthulhu.shutdown() + return False + + GLib.timeout_add(100, _delayed_shutdown) + return True + + def shutdown_service(self, bus: SessionMessageBus, object_path_base: str) -> None: + """Releases D-Bus resources held by this service and its modules.""" + + msg = "DBUS SERVICE: Releasing D-Bus resources for service." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + for module_name in list(self._registered_modules): + module_object_path = f"{object_path_base}/{module_name}" + msg = ( + f"DBUS SERVICE: Shutting down and unpublishing module {module_name} " + f"from main service." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + try: + bus.unpublish_object(module_object_path) + except DBusError as e: + msg = f"DBUS SERVICE: Error unpublishing interface for {module_name}: {e}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._registered_modules.clear() + +else: + # Fallback classes when dasbus is not available + class CthulhuModuleDBusInterface: + """Fallback class when dasbus is not available.""" + def __init__(self, *args, **kwargs): + pass + + class CthulhuDBusServiceInterface: + """Fallback class when dasbus is not available.""" + def __init__(self, *args, **kwargs): + pass + +class CthulhuRemoteController: + """Manages Cthulhu's D-Bus service for remote control.""" + + SERVICE_NAME = "org.stormux.Cthulhu.Service" + OBJECT_PATH = "/org/stormux/Cthulhu/Service" + + def __init__(self) -> None: + self._dbus_service_interface: CthulhuDBusServiceInterface | None = None + self._is_running: bool = False + self._bus: SessionMessageBus | None = None + self._event_loop: EventLoop | None = None + self._pending_registrations: dict[str, object] = {} + self._total_commands: int = 0 + self._total_getters: int = 0 + self._total_setters: int = 0 + self._total_modules: int = 0 + self._dasbus_available = _dasbus_available + + def start(self) -> bool: + """Starts the D-Bus service.""" + + if not self._dasbus_available: + msg = "REMOTE CONTROLLER: dasbus library not available, D-Bus service disabled." + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + if self._is_running: + msg = "REMOTE CONTROLLER: Start called but service is already running." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "REMOTE CONTROLLER: Attempting to start D-Bus service." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + try: + self._bus = SessionMessageBus() + msg = ( + f"REMOTE CONTROLLER: SessionMessageBus acquired: " + f"{self._bus.connection.get_unique_name()}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + except DBusError as e: + self._bus = None + msg = f"REMOTE CONTROLLER: Failed to acquire D-Bus session bus: {e}" + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + return False + + self._dbus_service_interface = CthulhuDBusServiceInterface() + try: + self._bus.publish_object(self.OBJECT_PATH, self._dbus_service_interface) + self._bus.register_service(self.SERVICE_NAME) + except DBusError as e: + msg = f"REMOTE CONTROLLER: Failed to publish service or request name: {e}" + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + if self._dbus_service_interface and self._bus: + try: + self._bus.unpublish_object(self.OBJECT_PATH) + except DBusError: + pass + self._dbus_service_interface = None + self._bus = None + return False + + self._is_running = True + msg = ( + f"REMOTE CONTROLLER: Service started name={self.SERVICE_NAME} " + f"path={self.OBJECT_PATH}." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._process_pending_registrations() + self._print_registration_summary() + return True + + def _process_pending_registrations(self) -> None: + """Processes any module registrations that were queued before the service was ready.""" + + if not self._pending_registrations: + return + + msg = ( + f"REMOTE CONTROLLER: Processing {len(self._pending_registrations)} " + f"pending module registrations." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + for module_name, module_instance in self._pending_registrations.items(): + msg = f"REMOTE CONTROLLER: Processing pending registration for {module_name}." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._register_decorated_commands_internal(module_name, module_instance) + + self._pending_registrations.clear() + + def register_decorated_module(self, module_name: str, module_instance) -> None: + """Registers a module's decorated D-Bus commands.""" + + if not self._dasbus_available: + return + + if not self._is_running or not self._dbus_service_interface or not self._bus: + msg = ( + f"REMOTE CONTROLLER: Service not ready; queuing decorated registration " + f"for {module_name}." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._pending_registrations[module_name] = module_instance + return + + self._register_decorated_commands_internal(module_name, module_instance) + + def _register_decorated_commands_internal(self, module_name: str, module_instance) -> None: + """Internal method that registers decorated commands from a module instance.""" + + if not self._is_running or not self._dbus_service_interface or not self._bus: + msg = ( + f"REMOTE CONTROLLER: Internal error - _register_decorated_commands_internal " + f"called for {module_name} but service is not ready." + ) + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + return + + handlers_info = [] + commands_count = 0 + getters_count = 0 + setters_count = 0 + + for attr_name in dir(module_instance): + attr = getattr(module_instance, attr_name) + # Command + if callable(attr) and hasattr(attr, "dbus_command_description"): + description = attr.dbus_command_description + def _create_wrapper(method=attr): + def _wrapper(notify_user): + event = _get_input_event().RemoteControllerEvent() + script = cthulhu_state.activeScript + return method(script=script, event=event, notify_user=notify_user) + return _wrapper + handler_info = _HandlerInfo( + python_function_name=attr_name, + description=description, + action=_create_wrapper(), + handler_type=HandlerType.COMMAND + ) + handlers_info.append(handler_info) + commands_count += 1 + msg = f"REMOTE CONTROLLER: Found decorated command '{attr_name}': {description}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + # Parameterized Command + elif callable(attr) and hasattr(attr, "dbus_parameterized_command_description"): + description = attr.dbus_parameterized_command_description + def _create_parameterized_wrapper(method=attr): + def _wrapper(**kwargs): + event = _get_input_event().RemoteControllerEvent() + script = cthulhu_state.activeScript + if script is None: + manager = script_manager.getManager() + script = manager.getDefaultScript() + return method(script=script, event=event, **kwargs) + return _wrapper + handler_info = _HandlerInfo( + python_function_name=attr_name, + description=description, + action=_create_parameterized_wrapper(), + handler_type=HandlerType.PARAMETERIZED_COMMAND, + parameters=_extract_function_parameters(attr) + ) + handlers_info.append(handler_info) + commands_count += 1 + msg = f"REMOTE CONTROLLER: Found decorated parameterized command '{attr_name}': {description}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + # Getter + elif callable(attr) and hasattr(attr, "dbus_getter_description"): + description = attr.dbus_getter_description + def _create_getter_wrapper(method=attr): + def _wrapper(_notify_user=None): + return method() + return _wrapper + handler_info = _HandlerInfo( + python_function_name=attr_name, + description=description, + action=_create_getter_wrapper(), + handler_type=HandlerType.GETTER + ) + handlers_info.append(handler_info) + getters_count += 1 + msg = f"REMOTE CONTROLLER: Found decorated getter '{attr_name}': {description}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + # Setter + elif callable(attr) and hasattr(attr, "dbus_setter_description"): + description = attr.dbus_setter_description + def _create_setter_wrapper(method=attr): + def _wrapper(value): + return method(value) + return _wrapper + handler_info = _HandlerInfo( + python_function_name=attr_name, + description=description, + action=_create_setter_wrapper(), + handler_type=HandlerType.SETTER + ) + handlers_info.append(handler_info) + setters_count += 1 + msg = f"REMOTE CONTROLLER: Found decorated setter '{attr_name}': {description}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not handlers_info: + return + + self._total_commands += commands_count + self._total_getters += getters_count + self._total_setters += setters_count + self._total_modules += 1 + + self._dbus_service_interface.add_module_interface( + module_name, handlers_info, self._bus, self.OBJECT_PATH) + msg = ( + f"REMOTE CONTROLLER: Successfully registered {len(handlers_info)} " + f"commands/getters/setters for module {module_name}." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def deregister_module_commands(self, module_name: str) -> bool: + """Deregisters D-Bus commands for a Cthulhu module.""" + + if not self._dasbus_available: + return False + + if module_name in self._pending_registrations: + msg = f"REMOTE CONTROLLER: Removing pending registration for {module_name}." + debug.printMessage(debug.LEVEL_INFO, msg, True) + del self._pending_registrations[module_name] + return True + + if not self._is_running or not self._dbus_service_interface or not self._bus: + msg = ( + f"REMOTE CONTROLLER: Cannot deregister commands for {module_name}; " + "service not running or bus not available." + ) + debug.printMessage(debug.LEVEL_WARNING, msg, True) + return False + + return self._dbus_service_interface.remove_module_interface( + module_name, self._bus, self.OBJECT_PATH) + + def shutdown(self) -> None: + """Shuts down the D-Bus service.""" + + if not self._dasbus_available: + return + + if not self._is_running: + msg = "REMOTE CONTROLLER: Shutdown called but service is not running." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "REMOTE CONTROLLER: Attempting to shut down D-Bus service." + debug.printMessage(debug.LEVEL_INFO, msg, True) + if self._dbus_service_interface and self._bus: + self._dbus_service_interface.shutdown_service(self._bus, self.OBJECT_PATH) + try: + self._bus.unpublish_object(self.OBJECT_PATH) + except DBusError as e: + msg = f"REMOTE CONTROLLER: Error unpublishing main service object: {e}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._dbus_service_interface = None + + if self._bus: + try: + self._bus.unregister_service(self.SERVICE_NAME) + except DBusError as e: + msg = f"REMOTE CONTROLLER: Error releasing bus name: {e}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._bus.disconnect() + self._bus = None + + self._is_running = False + msg = "REMOTE CONTROLLER: D-Bus service shut down." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._pending_registrations.clear() + self._total_commands = 0 + self._total_getters = 0 + self._total_setters = 0 + self._total_modules = 0 + + def is_running(self) -> bool: + """Checks if the D-Bus service is currently running.""" + + return self._is_running + + def _count_system_commands(self) -> int: + """Counts the system-wide D-Bus commands available on the main service interface.""" + + if not self._dbus_service_interface: + return 0 + + system_commands = 0 + for attr_name in dir(self._dbus_service_interface): + if not attr_name.startswith("_") and attr_name[0].isupper(): + attr = getattr(self._dbus_service_interface, attr_name) + if callable(attr) and hasattr(attr, "__doc__"): + system_commands += 1 + return system_commands + + def _print_registration_summary(self) -> None: + """Prints a summary of all registered D-Bus handlers.""" + + system_commands_count = self._count_system_commands() + total_handlers = self._total_commands + self._total_getters + self._total_setters + msg = ( + f"REMOTE CONTROLLER: Registration complete. Summary: " + f"{self._total_modules} modules, " + f"{self._total_commands} module commands, " + f"{self._total_getters} module getters, " + f"{self._total_setters} module setters, " + f"{system_commands_count} system commands. " + f"Total handlers: {total_handlers + system_commands_count}." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + +_remote_controller: CthulhuRemoteController = CthulhuRemoteController() + +def get_remote_controller() -> CthulhuRemoteController: + """Returns the CthulhuRemoteController singleton.""" + + return _remote_controller \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/debug.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/debug.py new file mode 100644 index 0000000..47a2566 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/debug.py @@ -0,0 +1,587 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides debug utilities for Cthulhu. Debugging is managed by a debug +level, which is held in the debugLevel field. All other methods take +a debug level, which is compared to the current debug level to +determine if the content should be output.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import inspect +import traceback +import os +import re +import subprocess +import sys +import types + +from datetime import datetime + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +# Used to turn off all debugging. +# +LEVEL_OFF = 10000 + +# Used to describe events of considerable importance and which will prevent +# normal program execution. +# +LEVEL_SEVERE = 1000 + +# Used to describe events of interest to end users or system managers or which +# indicate potential problems, but which Cthulhu can deal with without crashing. +# +LEVEL_WARNING = 900 + +# Used to indicate reasonably significant messages that make sense to end users +# and system managers. +# +# For the purposes of Cthulhu, LEVEL_INFO means display the text being sent to +# speech and braille. +# +LEVEL_INFO = 800 + +# Used to indicate static configuration information to assist in debugging +# problems that may be associated with a particular configuration. +# +# For the purposes of Cthulhu, LEVEL_CONFIGURATION means display the various +# aspects of whether a particular feature (e.g., speech, braille, etc.) +# is enabled or not as well as details about that feature. +# +LEVEL_CONFIGURATION = 700 + +# Used for lowest volume of detailed tracing information. +# +# For the purposes of Cthulhu, this is braille and keyboard input, script +# activation and deletion, locus of focus changes, and visual changes +# to the locus of focus. +# +LEVEL_FINE = 600 + +# Used for medium volume of detailed tracing information. +# +# For the purposes of Cthulhu, this is for debugging speech and braille +# generators and tracking the synthesis of device events. +# +LEVEL_FINER = 500 + +# Used for maximum volume of detailed tracing information. +# +# For the purposes of Cthulhu, this is for tracking all AT-SPI object +# events. NOTE that one can up the debug level of AT-SPI object +# events by setting the eventDebugLevel. In addition, one can filter +# events by setting eventDebugFilter to a regular expression that +# matches event type names. +# +LEVEL_FINEST = 400 + +# Used for all detailed tracing information, even finer than LEVEL_FINEST +# +LEVEL_ALL = 0 + +debugLevel = LEVEL_SEVERE + +# The debug file. If this is not set, then all debug output is done +# via stdout. If this is set, then all debug output is sent to the +# file. This can be useful for debugging because one can pass in a +# non-buffered file to better track down hangs. +# +debugFile = None + +# The debug filter should be either None (which means to match all +# events) or a compiled regular expression from the 're' module (see +# http://www.amk.ca/python/howto/regex/). The regular expression will +# be used as a matching function - if the event type creates a match +# in the regular expression, then it will be considered for output. A +# typical call to this method might look like: +# +# debug.eventDebugFilter = rc.compile('focus:|window:activate') +# +eventDebugLevel = LEVEL_FINEST +eventDebugFilter = None + +# If True, we output debug information for the event queue. We +# use this in addition to log level to prevent debug logic from +# bogging down event handling. +# +debugEventQueue = False + +# What module(s) should be traced if traceit is being used. By default +# we'll just attend to ourself. (And by default, we will not enable +# traceit.) Note that enabling this functionality will drag your system +# to a complete and utter halt and should only be used in extreme +# desperation by developers who are attempting to reproduce a very +# specific, immediate issue. Trust me. :-) Disabling braille monitor in +# this case is also strongly advised. +# +TRACE_MODULES = ['cthulhu'] + +# Specific modules to ignore with traceit. +# +TRACE_IGNORE_MODULES = ['traceback', 'linecache', 'locale', 'gettext', + 'logging', 'UserDict', 'encodings', 'posixpath', + 'genericpath', 're'] + +# Specific apps to trace with traceit. +# +TRACE_APPS = [] + +# What AT-SPI event(s) should be traced if traceit is being used. By +# default, we'll trace everything. Examples of what you might wish to +# do to narrow things down include: +# +# TRACE_EVENTS = ['object:state-changed', 'focus:'] +# (for any and all object:state-changed events plus focus: events) +# TRACE_EVENTS = ['object:state-changed:selected'] +# (if you know the exact event type of interest) +# +TRACE_EVENTS = [] + +# What role(s) should be traced if traceit is being used. By +# default, we'll trace everything. An example of what you might wish +# to do to narrow things down, if you know buttons trigger the problem: +# +# TRACE_ROLES = [Atspi.Role.PUSH_BUTTON, Atspi.Role.TOGGLE_BUTTON] +# +TRACE_ROLES = [] + +# Whether or not traceit should only trace the work being done when +# processing an actual event. This is when most bad things happen. +# So we'll default to True. +# +TRACE_ONLY_PROCESSING_EVENTS = True + +objEvent = None + +def printException(level): + """Prints out information regarding the current exception. + + Arguments: + - level: the accepted debug level + """ + + if level >= debugLevel: + println(level) + traceback.print_exc(100, debugFile) + println(level) + +def printStack(level): + """Prints out the current stack. + + Arguments: + - level: the accepted debug level + """ + + if level >= debugLevel: + println(level) + traceback.print_stack(None, 100, debugFile) + println(level) + +def _asString(obj): + if isinstance(obj, Atspi.Accessible): + result = AXObject.get_role_name(obj) + name = AXObject.get_name(obj) + if name: + result += f": '{name}'" + if not result: + result = "DEAD" + + return f"[{result}]" + + if isinstance(obj, Atspi.Event): + return ( + f"{obj.type} for {_asString(obj.source)} in " + f"{_asString(AXObject.get_application(obj.source))} " + f"({obj.detail1}, {obj.detail2}, {_asString(obj.any_data)})" + ) + + if isinstance(obj, (Atspi.Role, Atspi.StateType, Atspi.CollectionMatchType)): + return obj.value_nick + + if isinstance(obj, list): + return f"[{', '.join(map(_asString, obj))}]" + + if isinstance(obj, types.FunctionType): + if hasattr(obj, "__self__"): + return f"{obj.__module__}.{obj.__self__.__class__.__name__}.{obj.__name__}" + return f"{obj.__module__}.{obj.__name__}" + + if isinstance(obj, types.FrameType): + module_name = inspect.getmodulename(obj.f_code.co_filename) + return f"{module_name}.{obj.f_code.co_name}" + + if isinstance(obj, inspect.FrameInfo): + module_name = inspect.getmodulename(obj.filename) + return f"{module_name}.{obj.function}" + + return str(obj) + +def printTokens(level, tokens, timestamp=False, stack=False): + if level < debugLevel: + return + + text = " ".join(map(_asString, tokens)) + text = re.sub(r"[ \u00A0]+", " ", text) + text = re.sub(r" (?=[,.:)])(?![\n])", "", text) + println(level, text, timestamp, stack) + +def printMessage(level, text, timestamp=False, stack=False): + if level < debugLevel: + return + + println(level, text, timestamp, stack) + +def _stackAsString(max_frames=4): + callers = [] + current_module = inspect.getmodule(inspect.currentframe()) + stack = inspect.stack() + for i in range(1, len(stack)): + frame = stack[i] + module = inspect.getmodule(frame[0]) + if module == current_module: + continue + if frame.function == 'main': + continue + if module is None or module.__name__ is None: + continue + callers.append(frame) + if len(callers) >= max_frames: + break + + callers.reverse() + return " > ".join(map(_asString, callers)) + +def println(level, text="", timestamp=False, stack=False): + """Prints the text to stderr unless debug is enabled. + + If debug is enabled the text will be redirected to the + file debugFile. + + Arguments: + - level: the accepted debug level + - text: the text to print (default is a blank line) + """ + + if level >= debugLevel: + text = text.replace("\ufffc", "[OBJ]") + if timestamp: + text = text.replace("\n", f"\n{' ' * 18}") + text = f"{text} - {datetime.now().strftime('%H:%M:%S.%f')}" + if stack: + text += f" {_stackAsString()}" + + if debugFile: + try: + debugFile.writelines([text, "\n"]) + except TypeError: + text = "TypeError when trying to write text" + debugFile.writelines([text, "\n"]) + except Exception: + text = "Exception when trying to write text" + debugFile.writelines([text, "\n"]) + else: + try: + sys.stderr.writelines([text, "\n"]) + except TypeError: + text = "TypeError when trying to write text" + sys.stderr.writelines([text, "\n"]) + except Exception: + text = "Exception when trying to write text" + sys.stderr.writelines([text, "\n"]) + +def printResult(level, result=None): + """Prints the return result, along with information about the + method, arguments, and any errors encountered.""" + + if level < debugLevel: + return + + stack = inspect.stack() + current, prev = stack[1], stack[2] + frame = current[0] + + # To better print arguments which are accessible objects + args = inspect.getargvalues(frame) + for key, value in list(args.locals.items()): + args.locals[key] = str(value) + fArgs = str.replace(inspect.formatargvalues(*args), "'", "") + + callString = 'CALL: %s.%s (line %s) -> %s.%s%s' % ( + inspect.getmodulename(prev[1]), prev[3], prev[2], + inspect.getmodulename(current[1]), current[3], fArgs) + string = f'{callString}\nRESULT: {result}' + println(level, f'{string}') + +def printObjectEvent(level, event, sourceInfo=None, timestamp=False): + """Prints out an Python Event object. The given level may be + overridden if the eventDebugLevel is greater. Furthermore, only + events with event types matching the eventDebugFilter regular + expression will be printed. + + Arguments: + - level: the accepted debug level + - event: the Python Event to print + - sourceInfo: additional string to print out + """ + + if eventDebugFilter and not eventDebugFilter.match(event.type): + return + + level = max(level, eventDebugLevel) + + anydata = event.any_data + if isinstance(anydata, str) and len(anydata) > 100: + anydata = f"{anydata[0:100]} (...)" + + text = "OBJECT EVENT: %s (%d, %d, %s)" \ + % (event.type, event.detail1, event.detail2, anydata) + println(level, text, timestamp) + + if sourceInfo: + println(level, f"{' ' * 18}{sourceInfo}", timestamp) + +def printInputEvent(level, string, timestamp=False): + """Prints out an input event. The given level may be overridden + if the eventDebugLevel (see setEventDebugLevel) is greater. + + Arguments: + - level: the accepted debug level + - string: the string representing the input event + """ + + println(max(level, eventDebugLevel), string, timestamp) + +def printDetails(level, indent, accessible, includeApp=True, timestamp=False): + """Lists the details of the given accessible with the given + indentation. + + Arguments: + - level: the accepted debug level + - indent: a string containing spaces for indentation + - accessible: the accessible whose details are to be listed + - includeApp: if True, include information about the app + """ + + if level >= debugLevel and accessible: + println(level, + getAccessibleDetails(level, accessible, indent, includeApp), + timestamp) + +def getAccessibleDetails(level, acc, indent="", includeApp=True): + """Returns a string, suitable for printing, that describes the + given accessible. + + Arguments: + - indent: A string to prefix the output with + - includeApp: If True, include information about the app + for this accessible. + """ + + if level < debugLevel: + return "" + + if includeApp: + string = indent + f"app='{AXObject.application_as_string(acc)}' " + else: + string = indent + + if AXObject.is_dead(acc): + string += "(exception fetching data)" + return string + + name_string = "name='%s'".replace("\n", "\\n") % AXObject.get_name(acc) + desc_string = "%sdescription='%s'".replace("\n", "\\n") % \ + (indent, AXObject.get_description(acc)) + role_string = f"role='{AXObject.get_role_name(acc)}'" + path_string = f"{indent}path={AXObject.get_path(acc)}" + state_string = f"{indent}states='{AXObject.state_set_as_string(acc)}'" + rel_string = f"{indent}relations='{AXObject.relations_as_string(acc)}'" + actions_string = f"{indent}actions='{AXObject.actions_as_string(acc)}'" + iface_string = f"{indent}interfaces='{AXObject.supported_interfaces_as_string(acc)}'" + attr_string = f"{indent}attributes='{AXObject.attributes_as_string(acc)}'" + + string += "%s %s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" \ + % (name_string, role_string, desc_string, state_string, rel_string, + actions_string, iface_string, attr_string, path_string) + return string + +# The following code originated from the following URL: +# +# http://www.dalkescientific.com/writings/diary/archive/ \ +# 2005/04/20/tracing_python_code.html +# +import linecache + +def _getFileAndModule(frame): + filename, module = None, None + try: + filename = frame.f_globals["__file__"] + module = frame.f_globals["__name__"] + except Exception: + pass + else: + if (filename.endswith(".pyc") or filename.endswith(".pyo")): + filename = filename[:-1] + + return filename, module + +def _shouldTraceIt(): + if not objEvent: + return not TRACE_ONLY_PROCESSING_EVENTS + + eventSource = objEvent.source + if TRACE_APPS: + app = AXObject.get_application(eventSource) + if AXObject.get_name(app) not in TRACE_APPS: + return False + + if TRACE_ROLES and AXObject.get_role(eventSource) not in TRACE_ROLES: + return False + + if TRACE_EVENTS and \ + not [x for x in map(objEvent.type.startswith, TRACE_EVENTS) if x]: + return False + + return True + +def traceit(frame, event, arg): + """Line tracing utility to output all lines as they are executed by + the interpreter. This is to be used by sys.settrace and is for + debugging purposes. + + Arguments: + - frame: is the current stack frame + - event: 'call', 'line', 'return', 'exception', 'c_call', 'c_return', + or 'c_exception' + - arg: depends on the event type (see docs for sys.settrace) + """ + + if not _shouldTraceIt(): + return None + + filename, module = _getFileAndModule(frame) + if not (filename and module): + return traceit + if module in TRACE_IGNORE_MODULES: + return traceit + if TRACE_MODULES and module.split('.')[0] not in TRACE_MODULES: + return traceit + if event not in ['call', 'line', 'return']: + return traceit + + lineno = frame.f_lineno + line = linecache.getline(filename, lineno).rstrip() + output = f'TRACE {module}:{lineno}: {line}' + + if event == 'call': + argvals = inspect.getargvalues(frame) + keys = [x for x in argvals[0] if x != 'self'] + try: + values = list(map(argvals[3].get, keys)) + except TypeError: + if len(keys) == 1 and isinstance(keys[0], list): + values = list(map(argvals[3].get, keys[0])) + else: + return traceit + for i, key in enumerate(keys): + output += f'\n ARG {key}={values[i]}' + + lineElements = line.strip().split() + if lineElements and lineElements[0] == 'return': + if event == 'line': + return traceit + output = f'{output} (rv: {arg})' + + println(LEVEL_ALL, output) + + return traceit + +def getOpenFDCount(pid): + procs = subprocess.check_output([ 'lsof', '-w', '-Ff', '-p', str(pid)]) + procs = procs.decode('UTF-8').split('\n') + files = list(filter(lambda s: s and s[0] == 'f' and s[1:].isdigit(), procs)) + + return len(files) + +def getCmdline(pid): + try: + openFile = os.popen(f'cat /proc/{pid}/cmdline') + cmdline = openFile.read() + openFile.close() + except Exception: + cmdline = '(Could not obtain cmdline)' + cmdline = cmdline.replace('\x00', ' ') + + return cmdline + +def pidOf(procName): + openFile = subprocess.Popen(f'pgrep {procName}', + shell=True, + stdout=subprocess.PIPE).stdout + pids = openFile.read() + openFile.close() + return [int(p) for p in pids.split()] + +def examineProcesses(force=False): + if force: + level = LEVEL_OFF + else: + level = LEVEL_ALL + + desktop = AXUtilities.get_desktop() + println(level, 'INFO: Desktop has %i apps:' % AXObject.get_child_count(desktop), True) + for i, app in enumerate(AXObject.iter_children(desktop)): + pid = AXObject.get_process_id(app) + cmd = getCmdline(pid) + fds = getOpenFDCount(pid) + name = AXObject.get_name(app) + if name == '': + name = 'WARNING: Possible hang or dead app' + println(level, '%3i. %s (pid: %s) %s file descriptors: %i' \ + % (i+1, name, pid, cmd, fds), True) + + # Other 'suspect' processes which might not show up as accessible apps. + otherApps = ['apport'] + for app in otherApps: + pids = pidOf(app) + if not pids: + println(level, f'INFO: no pid for {app}', True) + continue + + for pid in pids: + cmd = getCmdline(pid) + fds = getOpenFDCount(pid) + println(level, 'INFO: %s (pid: %s) %s file descriptors: %i' \ + % (app, pid, cmd, fds), True) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/desktop_keyboardmap.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/desktop_keyboardmap.py new file mode 100644 index 0000000..f447dde --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/desktop_keyboardmap.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" A list of common keybindings and unbound keys + pulled out from default.py: __getDesktopBindings() + with the goal of being more readable and less monolithic. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs, Mesar Hameed." +__license__ = "LGPL" + +from . import keybindings + +# Storing values +defaultModifierMask = keybindings.defaultModifierMask +CTHULHU_MODIFIER_MASK = keybindings.CTHULHU_MODIFIER_MASK +NO_MODIFIER_MASK = keybindings.NO_MODIFIER_MASK +CTHULHU_SHIFT_MODIFIER_MASK = keybindings.CTHULHU_SHIFT_MODIFIER_MASK + +keymap = ( + + ("KP_Divide", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "routePointerToItemHandler"), + + # We want the user to be able to combine modifiers with the + # mouse click (e.g. to Shift+Click and select), therefore we + # do not "care" about the modifiers -- unless it's the Cthulhu + # modifier. + # + ("KP_Divide", CTHULHU_MODIFIER_MASK, NO_MODIFIER_MASK, + "leftClickReviewItemHandler"), + + ("KP_Multiply", CTHULHU_MODIFIER_MASK, NO_MODIFIER_MASK, + "rightClickReviewItemHandler"), + + ("KP_Add", defaultModifierMask, NO_MODIFIER_MASK, + "sayAllHandler", 1), + + ("KP_Delete", defaultModifierMask, NO_MODIFIER_MASK, + "findHandler"), + + ("KP_Delete", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "findNextHandler"), + + ("KP_Delete", defaultModifierMask, CTHULHU_SHIFT_MODIFIER_MASK, + "findPreviousHandler"), +) \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dynamic_api_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dynamic_api_manager.py new file mode 100644 index 0000000..e377f75 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/dynamic_api_manager.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import gi +from gi.repository import GObject + +from cthulhu import resource_manager + +class DynamicApiManager(): + def __init__(self, app): + self.app = app + self.resourceManager = self.app.getResourceManager() + self.api = {'Cthulhu': self.app} + def registerAPI(self, key, value, application = '', contextName = None, overwrite = False): + if not overwrite: + try: + d = self.api[application][key] + return + except KeyError: + pass + # add profile + try: + d = self.api[application] + except KeyError: + self.api[application]= {} + # add dynamic API + self.api[application][key] = value + resourceContext = self.resourceManager.getResourceContext(contextName) + if resourceContext: + resourceEntry = resource_manager.ResourceEntry('api', key, value, value, key) + resourceContext.addAPI(application, key, resourceEntry) + + def unregisterAPI(self, key, application = '', contextName = None): + ok = False + try: + del self.api[application][key] + ok = True + except: + print('API Key: "{}/{}" not found,'.format(application, key)) + resourceContext = self.resourceManager.getResourceContext(contextName) + if resourceContext: + resourceContext.removeAPI(application, key) + return ok + def getAPI(self, key, application = '', fallback = True): + # get dynamic API + api = None + + try: + api = self.api[application][key] + return api + except: + if not fallback: + print('API Key: "{}/{}" not found,'.format(application, key)) + return None + + # we already tried this + if application == '': + return api + + try: + api = self.api[application][''] + except: + print('API Key: "{}/{}" not found,'.format(application, key)) + + return api diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/event_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/event_manager.py new file mode 100644 index 0000000..8f2db5d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/event_manager.py @@ -0,0 +1,1231 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2011. Cthulhu Team." +__license__ = "LGPL" + +import gi +gi.require_version('Atspi', '2.0') +from gi.repository import Atspi +from gi.repository import GLib +import pyatspi +import queue +import threading +import time + +from . import debug +from . import input_event +from . import input_event_manager +from . import cthulhu_state +from . import script_manager +from . import settings +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +_scriptManager = script_manager.getManager() + +class EventManager: + + EMBEDDED_OBJECT_CHARACTER = '\ufffc' + + def __init__(self, asyncMode=True): + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Initializing', True) + debug.printMessage(debug.LEVEL_INFO, f'EVENT MANAGER: Async Mode is {asyncMode}', True) + self._asyncMode = asyncMode + self._scriptListenerCounts = {} + self._active = False + self._enqueueCount = 0 + self._dequeueCount = 0 + self._eventQueue = queue.Queue(0) + self._gidleId = 0 + self._gidleLock = threading.Lock() + self._gilSleepTime = 0.00001 + self._synchronousToolkits = ['VCL'] + self._eventsSuspended = False + self._listener = Atspi.EventListener.new(self._enqueue) + + # Note: These must match what the scripts registered for, otherwise + # Atspi might segfault. + # + # Events we don't want to suspend include: + # object:text-changed:insert - marco + # object:property-change:accessible-name - gnome-shell issue #6925 + self._suspendableEvents = ['object:children-changed:add', + 'object:children-changed:remove', + 'object:state-changed:sensitive', + 'object:state-changed:showing', + 'object:text-changed:delete'] + self._eventsTriggeringSuspension = [] + self._ignoredEvents = ['object:bounds-changed', + 'object:state-changed:defunct', + 'object:property-change:accessible-parent'] + self._parentsOfDefunctDescendants = [] + + cthulhu_state.device = None + self.newKeyHandlingActive = False + self.legacyKeyHandlingActive = False + self.forceLegacyKeyHandling = False + + debug.printMessage(debug.LEVEL_INFO, 'Event manager initialized', True) + + def activate(self): + """Called when this event manager is activated.""" + + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Activating', True) + self.setKeyHandling(True) # Enable new InputEventManager for global keyboard capture + + self._active = True + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Activated', True) + + def activateNewKeyHandling(self): + if not self.newKeyHandlingActive: + try: + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Attempting to activate new keyboard handling', True) + # Use the new InputEventManager instead of direct Atspi.Device + self._inputEventManager = input_event_manager.getManager() + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: InputEventManager obtained', True) + self._inputEventManager.start_key_watcher() + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Key watcher started', True) + cthulhu_state.device = self._inputEventManager._device # For compatibility + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f'EVENT MANAGER: New keyboard handling failed: {e}', True) + self.forceLegacyKeyHandling = True + self.activateLegacyKeyHandling() + return + + self.newKeyHandlingActive = True + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: New keyboard handling activated with InputEventManager', True) + + # Notify plugin system that device is now available for keybinding registration + from . import cthulhu + if hasattr(cthulhu, 'cthulhuApp') and cthulhu.cthulhuApp: + plugin_manager = cthulhu.cthulhuApp.getPluginSystemManager() + if plugin_manager: + pass # plugin_manager.register_plugin_keybindings_with_active_script() + + def activateLegacyKeyHandling(self): + if not self.legacyKeyHandlingActive: + self.registerKeystrokeListener(self._processKeyboardEvent) + self.legacyKeyHandlingActive = True + + def setKeyHandling(self, new): + if new and not self.forceLegacyKeyHandling: + self.deactivateLegacyKeyHandling() + self.activateNewKeyHandling() + else: + self.deactivateNewKeyHandling() + self.activateLegacyKeyHandling() + + def deactivate(self): + """Called when this event manager is deactivated.""" + + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Deactivating', True) + self._active = False + self._eventQueue = queue.Queue(0) + self._scriptListenerCounts = {} + self.deactivateLegacyKeyHandling() + debug.printMessage(debug.LEVEL_INFO, 'EVENT MANAGER: Deactivated', True) + + def deactivateNewKeyHandling(self): + if self.newKeyHandlingActive: + if hasattr(self, '_inputEventManager'): + self._inputEventManager.stop_key_watcher() + self._inputEventManager = None + cthulhu_state.device = None + self.newKeyHandlingActive = False + + def deactivateLegacyKeyHandling(self): + if self.legacyKeyHandlingActive: + self.deregisterKeystrokeListener(self._processKeyboardEvent) + self.legacyKeyHandlingActive = False + + def ignoreEventTypes(self, eventTypeList): + for eventType in eventTypeList: + if eventType not in self._ignoredEvents: + self._ignoredEvents.append(eventType) + + def unignoreEventTypes(self, eventTypeList): + for eventType in eventTypeList: + if eventType in self._ignoredEvents: + self._ignoredEvents.remove(eventType) + + def _isDuplicateEvent(self, event): + """Returns True if this event is already in the event queue.""" + + if self._inFlood() and self._prioritizeDuringFlood(event): + return False + + def isSame(x): + return x.type == event.type \ + and x.source == event.source \ + and x.detail1 == event.detail1 \ + and x.detail2 == event.detail2 \ + and x.any_data == event.any_data + + for e in self._eventQueue.queue: + if isSame(e): + return True + + return False + + def _ignore(self, event): + """Returns True if this event should be ignored.""" + + app = AXObject.get_application(event.source) + debug.printMessage(debug.LEVEL_INFO, '') + tokens = ["EVENT MANAGER:", event.type, "from", app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if self._eventsSuspended: + tokens = ["EVENT MANAGER: Suspended events:", ', '.join(self._suspendableEvents)] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not self._active: + msg = 'EVENT MANAGER: Ignoring because event manager is not active' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if list(filter(event.type.startswith, self._ignoredEvents)): + msg = 'EVENT MANAGER: Ignoring because event type is ignored' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXObject.get_name(app) == 'gnome-shell': + if event.type.startswith('object:children-changed:remove'): + msg = 'EVENT MANAGER: Ignoring event based on type and app' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if event.type.startswith('window'): + msg = 'EVENT MANAGER: Not ignoring because event type is never ignored' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if event.type.startswith('mouse:button'): + msg = 'EVENT MANAGER: Not ignoring because event type is never ignored' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._isDuplicateEvent(event): + msg = 'EVENT MANAGER: Ignoring duplicate event' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + # Thunderbird spams us with these when a message list thread is expanded or collapsed. + if event.type.endswith('system') \ + and AXObject.get_name(app).lower().startswith('thunderbird'): + if AXUtilities.is_table_related(event.source) \ + or AXUtilities.is_tree_related(event.source) \ + or AXUtilities.is_section(event.source): + msg = 'EVENT MANAGER: Ignoring system event based on role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._inDeluge() and self._ignoreDuringDeluge(event): + msg = 'EVENT MANAGER: Ignoring event type due to deluge' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + script = cthulhu_state.activeScript + if event.type.startswith('object:children-changed') \ + or event.type.startswith('object:state-changed:sensitive'): + if not script: + msg = 'EVENT MANAGER: Ignoring because there is no active script' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + if script.app != app: + msg = 'EVENT MANAGER: Ignoring because event is not from active app' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if event.type.startswith('object:text-changed') \ + and self.EMBEDDED_OBJECT_CHARACTER in event.any_data \ + and not event.any_data.replace(self.EMBEDDED_OBJECT_CHARACTER, ""): + # We should also get children-changed events telling us the same thing. + # Getting a bunch of both can result in a flood that grinds us to a halt. + msg = 'EVENT MANAGER: Ignoring because changed text is only embedded objects' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + # TODO - JD: For now we won't ask for the name. Simply asking for the name should + # not break anything, and should be a reliable way to quickly identify defunct + # objects. But apparently the mere act of asking for the name causes Cthulhu to stop + # presenting Eclipse (and possibly other) applications. This might be an AT-SPI2 + # issue, but until we know for certain.... + #name = Atspi.Accessible.get_name(event.source) + + if AXUtilities.has_no_state(event.source): + msg = 'EVENT MANAGER: Ignoring event due to empty state set' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXUtilities.is_defunct(event.source): + msg = 'EVENT MANAGER: Ignoring event from defunct source' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + role = AXObject.get_role(event.source) + if event.type.startswith('object:property-change:accessible-name'): + if role in [Atspi.Role.CANVAS, + Atspi.Role.ICON, + Atspi.Role.LIST_ITEM, # Web app spam + Atspi.Role.LIST, # Web app spam + Atspi.Role.PANEL, # TeamTalk5 spam + Atspi.Role.SECTION, # Web app spam + Atspi.Role.TABLE_ROW, # Thunderbird spam + Atspi.Role.TABLE_CELL, # Thunderbird spam + Atspi.Role.TREE_ITEM, # Thunderbird spam + Atspi.Role.IMAGE, # Thunderbird spam + Atspi.Role.MENU, + Atspi.Role.MENU_ITEM]: + msg = 'EVENT MANAGER: Ignoring event type due to role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + # TeamTalk5 is notoriously spammy here, and name change events on widgets are + # typically only presented if they are focused. + if not AXUtilities.is_focused(event.source) \ + and role in [Atspi.Role.PUSH_BUTTON, + Atspi.Role.CHECK_BOX, + Atspi.Role.RADIO_BUTTON]: + msg = 'EVENT MANAGER: Ignoring event type due to role and state' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + elif event.type.startswith('object:property-change:accessible-value'): + if role == Atspi.Role.SPLIT_PANE and not AXUtilities.is_focused(event.source): + msg = 'EVENT MANAGER: Ignoring event type due to role and state' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + elif event.type.startswith('object:text-changed:insert') and event.detail2 > 1000 \ + and role in [Atspi.Role.TEXT, Atspi.Role.STATIC]: + msg = 'EVENT MANAGER: Ignoring because inserted text has more than 1000 chars' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + elif event.type.startswith('object:state-changed:sensitive'): + if role in [Atspi.Role.MENU_ITEM, + Atspi.Role.MENU, + Atspi.Role.FILLER, + Atspi.Role.PANEL, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM]: + msg = 'EVENT MANAGER: Ignoring event type due to role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + elif event.type.startswith('object:state-changed:selected'): + if not event.detail1 and role in [Atspi.Role.PUSH_BUTTON]: + msg = 'EVENT MANAGER: Ignoring event type due to role and detail1' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + elif event.type.startswith('object:state-changed:showing'): + if role not in [Atspi.Role.ALERT, + Atspi.Role.ANIMATION, + Atspi.Role.INFO_BAR, + Atspi.Role.MENU, + Atspi.Role.NOTIFICATION, + Atspi.Role.DIALOG, + Atspi.Role.STATUS_BAR, + Atspi.Role.TOOL_TIP]: + msg = 'EVENT MANAGER: Ignoring event type due to role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + elif event.type.startswith('object:text-caret-moved'): + if role in [Atspi.Role.LABEL] and not AXUtilities.is_focused(event.source): + msg = 'EVENT MANAGER: Ignoring event type due to role and state' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + elif event.type.startswith('object:selection-changed'): + if event.source in self._parentsOfDefunctDescendants: + msg = 'EVENT MANAGER: Ignoring event from parent of defunct descendants' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXObject.is_dead(event.source): + msg = 'EVENT MANAGER: Ignoring event from dead source' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if event.type.startswith('object:children-changed') \ + or event.type.startswith('object:active-descendant-changed'): + if role in [Atspi.Role.MENU, + Atspi.Role.LAYERED_PANE, + Atspi.Role.MENU_ITEM]: + msg = 'EVENT MANAGER: Ignoring event type due to role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + if event.any_data is None: + msg = 'EVENT_MANAGER: Ignoring due to lack of event.any_data' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + if event.type.endswith('remove'): + if event.any_data == cthulhu_state.locusOfFocus: + msg = 'EVENT MANAGER: Locus of focus is being destroyed' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if AXObject.is_dead(cthulhu_state.locusOfFocus): + msg = 'EVENT MANAGER: Locus of focus is dead.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + tokens = ["EVENT MANAGER: Locus of focus:", cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + defunct = AXObject.is_dead(event.any_data) or AXUtilities.is_defunct(event.any_data) + if defunct: + msg = 'EVENT MANAGER: Ignoring event for potentially-defunct child/descendant' + debug.printMessage(debug.LEVEL_INFO, msg, True) + if AXUtilities.manages_descendants(event.source) \ + and event.source not in self._parentsOfDefunctDescendants: + self._parentsOfDefunctDescendants.append(event.source) + return True + + if event.source in self._parentsOfDefunctDescendants: + self._parentsOfDefunctDescendants.remove(event.source) + + # This should be safe. We do not have a reason to present a newly-added, + # but not focused image. We do not need to update live regions for images. + # This is very likely a completely and utterly useless event for us. The + # reason for ignoring it here rather than quickly processing it is the + # potential for event floods like we're seeing from matrix.org. + if AXUtilities.is_image(event.any_data): + msg = 'EVENT MANAGER: Ignoring event type due to role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + # In normal apps we would have caught this from the parent role. + # But gnome-shell has panel parents adding/removing menu items. + if event.type.startswith('object:children-changed'): + if AXUtilities.is_menu_item(event.any_data): + msg = 'EVENT MANAGER: Ignoring event type due to child role' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = 'EVENT MANAGER: Not ignoring due to lack of cause' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def _addToQueue(self, event, asyncMode): + debugging = debug.debugEventQueue + if debugging: + debug.printMessage(debug.LEVEL_ALL, " acquiring lock...") + self._gidleLock.acquire() + + if debugging: + debug.printMessage(debug.LEVEL_ALL, " ...acquired") + debug.printMessage(debug.LEVEL_ALL, " calling queue.put...") + debug.printMessage(debug.LEVEL_ALL, " (full=%s)" \ + % self._eventQueue.full()) + + self._eventQueue.put(event) + if debugging: + debug.printMessage(debug.LEVEL_ALL, " ...put complete") + + if asyncMode and not self._gidleId: + if self._gilSleepTime: + time.sleep(self._gilSleepTime) + self._gidleId = GLib.idle_add(self._dequeue) + + if debugging: + debug.printMessage(debug.LEVEL_ALL, " releasing lock...") + self._gidleLock.release() + if debug.debugEventQueue: + debug.printMessage(debug.LEVEL_ALL, " ...released") + + def _queuePrintln(self, e, isEnqueue=True, isPrune=None): + """Convenience method to output queue-related debugging info.""" + + if debug.LEVEL_INFO < debug.debugLevel: + return + + tokens = [] + if isinstance(e, input_event.KeyboardEvent): + tokens.extend([e.event_string, e.hw_code]) + elif isinstance(e, input_event.BrailleEvent): + tokens.append(e.event) + elif not debug.eventDebugFilter or debug.eventDebugFilter.match(e.type): + tokens.append(e) + else: + return + + if isPrune: + tokens[0:0] = ["EVENT MANAGER: Pruning"] + elif isPrune is not None: + tokens[0:0] = ["EVENT MANAGER: Not pruning"] + elif isEnqueue: + tokens[0:0] = ["EVENT MANAGER: Queueing"] + else: + tokens[0:0] = ["EVENT MANAGER: Dequeued"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def _suspendEvents(self, triggeringEvent): + self._eventsTriggeringSuspension.append(triggeringEvent) + + if self._eventsSuspended: + msg = "EVENT MANAGER: Events already suspended." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "EVENT MANAGER: Suspending events." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + for event in self._suspendableEvents: + self.deregisterListener(event) + + self._eventsSuspended = True + + def _unsuspendEvents(self, triggeringEvent, force=False): + if triggeringEvent in self._eventsTriggeringSuspension: + self._eventsTriggeringSuspension.remove(triggeringEvent) + + if not self._eventsSuspended: + msg = "EVENT MANAGER: Events already unsuspended." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self._eventsTriggeringSuspension and not force: + msg = "EVENT MANAGER: Events are suspended for another event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "EVENT MANAGER: Unsuspending events." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + for event in self._suspendableEvents: + self.registerListener(event) + + self._eventsSuspended = False + + def _shouldSuspendEventsFor(self, event): + if AXUtilities.is_frame(event.source) \ + or (AXUtilities.is_window(event.source) \ + and AXObject.get_application_toolkit_name(event.source) == "clutter"): + if event.type.startswith("window"): + msg = "EVENT MANAGER: Should suspend events for window event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + if event.type.endswith("active"): + msg = "EVENT MANAGER: Should suspend events for active event on window." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + if AXUtilities.is_document(event.source): + if event.type.endswith("busy") and event.detail1: + msg = "EVENT MANAGER: Should suspend events for busy:true event on document." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def _shouldUnsuspendEventsFor(self, event): + if event.type.startswith("object:state-changed:focused") and event.detail1: + msg = "EVENT MANAGER: Should unsuspend events for newly-focused object." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXUtilities.is_document(event.source): + if event.type.endswith("busy") and not event.detail1: + msg = "EVENT MANAGER: Should unsuspend events for busy:false event on document." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + if event.type.startswith("document:load-complete"): + msg = "EVENT MANAGER: Should unsuspend events for load-complete event on document." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def _didSuspendEventsFor(self, event): + return event in self._eventsTriggeringSuspension + + def _enqueue(self, e): + """Handles the enqueueing of all events destined for scripts. + + Arguments: + - e: an at-spi event. + """ + + if debug.debugEventQueue: + if self._enqueueCount: + msg = f"EVENT MANAGER: _enqueue entered before exiting (count={self._enqueueCount})" + debug.printMessage(debug.LEVEL_ALL, msg, True) + self._enqueueCount += 1 + + inputEvents = (input_event.KeyboardEvent, input_event.BrailleEvent) + isObjectEvent = not isinstance(e, inputEvents) + + try: + ignore = isObjectEvent and self._ignore(e) + except Exception as error: + tokens = ["EVENT MANAGER: Exception evaluating event:", e, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + ignore = True + if ignore: + if debug.debugEventQueue: + self._enqueueCount -= 1 + return + + self._queuePrintln(e) + + if self._inFlood() and self._prioritizeDuringFlood(e): + msg = 'EVENT MANAGER: Pruning event queue due to flood.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._pruneEventsDuringFlood() + + if isObjectEvent and self._shouldSuspendEventsFor(e): + self._suspendEvents(e) + + asyncMode = self._asyncMode + if isObjectEvent: + if isinstance(e, input_event.MouseButtonEvent): + asyncMode = True + elif AXObject.get_application_toolkit_name(e.source) in self._synchronousToolkits: + asyncMode = False + elif e.type.startswith("object:children-changed"): + asyncMode = AXUtilities.is_table(e.source) + elif AXUtilities.is_notification(e.source): + # To decrease the likelihood that the popup will be destroyed before we + # have its contents. + asyncMode = False + script = _scriptManager.getScript(AXObject.get_application(e.source), e.source) + script.eventCache[e.type] = (e, time.time()) + + self._addToQueue(e, asyncMode) + if not asyncMode: + self._dequeue() + + if debug.debugEventQueue: + self._enqueueCount -= 1 + + def _isNoFocus(self): + if cthulhu_state.locusOfFocus or cthulhu_state.activeWindow or cthulhu_state.activeScript: + return False + + msg = 'EVENT MANAGER: No focus' + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + return True + + def _onNoFocus(self): + if not self._isNoFocus(): + return False + + defaultScript = _scriptManager.getDefaultScript() + _scriptManager.setActiveScript(defaultScript, 'No focus') + defaultScript.idleMessage() + return False + + def _dequeue(self): + """Handles all events destined for scripts. Called by the GTK + idle thread.""" + + rerun = True + + if debug.debugEventQueue: + msg = f"EVENT MANAGER: Dequeue {self._dequeueCount}" + debug.printMessage(debug.LEVEL_ALL, msg, True) + self._dequeueCount += 1 + + try: + event = self._eventQueue.get_nowait() + self._queuePrintln(event, isEnqueue=False) + inputEvents = (input_event.KeyboardEvent, input_event.BrailleEvent) + if isinstance(event, inputEvents): + self._processInputEvent(event) + else: + debug.objEvent = event + debugging = not debug.eventDebugFilter \ + or debug.eventDebugFilter.match(event.type) + if debugging: + startTime = time.time() + msg = ( + f"\nvvvvv PROCESS OBJECT EVENT {event.type} " + f"(queue size: {self._eventQueue.qsize()}) vvvvv" + ) + debug.printMessage(debug.eventDebugLevel, msg, False) + self._processObjectEvent(event) + if self._didSuspendEventsFor(event): + self._unsuspendEvents(event) + elif self._eventsSuspended and self._shouldUnsuspendEventsFor(event): + self._unsuspendEvents(event, force=True) + + if debugging: + msg = ( + f"TOTAL PROCESSING TIME: {time.time() - startTime:.4f}" + f"\n^^^^^ PROCESS OBJECT EVENT {event.type} ^^^^^\n" + ) + debug.printMessage(debug.eventDebugLevel, msg, False) + + debug.objEvent = None + + self._gidleLock.acquire() + if self._eventQueue.empty(): + GLib.timeout_add(2500, self._onNoFocus) + self._gidleId = 0 + rerun = False # destroy and don't call again + self._gidleLock.release() + except queue.Empty: + msg = 'EVENT MANAGER: Attempted dequeue, but the event queue is empty' + debug.printMessage(debug.LEVEL_SEVERE, msg, True) + self._gidleId = 0 + rerun = False # destroy and don't call again + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + if debug.debugEventQueue: + self._dequeueCount -= 1 + msg = f"EVENT MANAGER: Leaving _dequeue. Count: {self._dequeueCount}" + debug.printMessage(debug.LEVEL_ALL, msg, True) + + return rerun + + def registerListener(self, eventType): + """Tells this module to listen for the given event type. + + Arguments: + - eventType: the event type. + """ + + msg = f'EVENT MANAGER: registering listener for: {eventType}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if eventType in self._scriptListenerCounts: + self._scriptListenerCounts[eventType] += 1 + else: + self._listener.register(eventType) + self._scriptListenerCounts[eventType] = 1 + + def deregisterListener(self, eventType): + """Tells this module to stop listening for the given event type. + + Arguments: + - eventType: the event type. + """ + + msg = f'EVENT MANAGER: deregistering listener for: {eventType}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if eventType not in self._scriptListenerCounts: + return + + self._scriptListenerCounts[eventType] -= 1 + if self._scriptListenerCounts[eventType] == 0: + self._listener.deregister(eventType) + del self._scriptListenerCounts[eventType] + + def registerScriptListeners(self, script): + """Tells the event manager to start listening for all the event types + of interest to the script. + + Arguments: + - script: the script. + """ + + tokens = ["EVENT MANAGER: Registering listeners for:", script] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + for eventType in script.listeners.keys(): + self.registerListener(eventType) + + def deregisterScriptListeners(self, script): + """Tells the event manager to stop listening for all the event types + of interest to the script. + + Arguments: + - script: the script. + """ + + tokens = ["EVENT MANAGER: De-registering listeners for:", script] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + for eventType in script.listeners.keys(): + self.deregisterListener(eventType) + + def registerKeystrokeListener(self, function, mask=None, kind=None): + """Register the keystroke listener on behalf of the caller.""" + + tokens = ["EVENT MANAGER: Registering keystroke listener function:", function] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if mask is None: + mask = list(range(256)) + + if kind is None: + kind = (Atspi.EventType.KEY_PRESSED_EVENT, Atspi.EventType.KEY_RELEASED_EVENT) + + pyatspi.Registry.registerKeystrokeListener(function, mask=mask, kind=kind) + + def deregisterKeystrokeListener(self, function, mask=None, kind=None): + """Deregister the keystroke listener on behalf of the caller.""" + + tokens = ["EVENT MANAGER: De-registering keystroke listener function:", function] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if mask is None: + mask = list(range(256)) + + if kind is None: + kind = (Atspi.EventType.KEY_PRESSED_EVENT, Atspi.EventType.KEY_RELEASED_EVENT) + + pyatspi.Registry.deregisterKeystrokeListener(function, mask=mask, kind=kind) + + def _processInputEvent(self, event): + """Processes the given input event based on the keybinding from the + currently-active script. + + Arguments: + - event: an instance of BrailleEvent or a KeyboardEvent + """ + + if not cthulhu_state.activeScript: + return + + if not isinstance(event, input_event.BrailleEvent): + return + + data = f"'{repr(event.event)}'" + eType = str(event.type).upper() + startTime = time.time() + + msg = f"\nvvvvv PROCESS {eType} {data} vvvvv" + debug.printMessage(debug.eventDebugLevel, msg, False) + + try: + cthulhu_state.activeScript.processBrailleEvent(event) + except Exception as error: + tokens = ["EVENT MANAGER: Exception processing event:", error] + debug.printTokens(debug.LEVEL_WARNING, tokens, True) + + msg = ( + f"TOTAL PROCESSING TIME: {time.time() - startTime:.4f}" + f"^^^^^ PROCESS {eType} {data} ^^^^^\n" + ) + debug.printMessage(debug.eventDebugLevel, msg, False) + + @staticmethod + def _getScriptForEvent(event): + """Returns the script associated with event.""" + + if event.type.startswith("mouse:"): + return _scriptManager.getScriptForMouseButtonEvent(event) + + script = None + app = AXObject.get_application(event.source) + if AXUtilities.is_defunct(app): + tokens = ["EVENT MANAGER:", app, "is defunct. Cannot get script for event."] + debug.printTokens(debug.LEVEL_WARNING, tokens, True) + return None + + skipCheck = { + "object:children-changed", + "object:column-reordered", + "object:row-reordered", + "object:property-change", + "object:selection-changed", + "object:state-changed:checked", + "object:state-changed:expanded", + "object:state-changed:indeterminate", + "object:state-changed:pressed", + "object:state-changed:selected", + "object:state-changed:sensitive", + "object:state-changed:showing", + "object:text-changed", + } + + check = not any(event.type.startswith(x) for x in skipCheck) + tokens = ["EVENT MANAGER: Getting script for", app, "check:", check] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + script = _scriptManager.getScript(app, event.source, sanityCheck=check) + tokens = ["EVENT MANAGER: Script is ", script] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return script + + def _isActivatableEvent(self, event, script=None): + """Determines if the event is one which should cause us to + change which script is currently active. + + Returns a (boolean, string) tuple indicating whether or not + this is an activatable event, and our reason (for the purpose + of debugging). + """ + + if not event.source: + return False, "event.source? What event.source??" + + if not script: + script = self._getScriptForEvent(event) + if not script: + return False, "There is no script for this event." + + if script == cthulhu_state.activeScript: + return False, "The script for this event is already active." + + if not script.isActivatableEvent(event): + return False, "The script says not to activate for this event." + + if script.forceScriptActivation(event): + return True, "The script insists it should be activated for this event." + + eType = event.type + + if eType.startswith('window:activate'): + windowActivation = True + else: + windowActivation = eType.startswith('object:state-changed:active') \ + and event.detail1 and AXUtilities.is_frame(event.source) + + if windowActivation: + if event.source != cthulhu_state.activeWindow: + return True, "Window activation" + else: + return False, "Window activation for already-active window" + + if eType.startswith('focus') \ + or (eType.startswith('object:state-changed:focused') + and event.detail1): + return True, "Event source claimed focus." + + if eType.startswith('object:state-changed:selected') and event.detail1 \ + and AXUtilities.is_menu(event.source) and AXUtilities.is_focusable(event.source): + return True, "Selection change in focused menu" + + # This condition appears with gnome-screensaver-dialog. + # See bug 530368. + if eType.startswith('object:state-changed:showing') \ + and AXUtilities.is_panel(event.source) and AXUtilities.is_modal(event.source): + return True, "Modal panel is showing." + + return False, "No reason found to activate a different script." + + def _eventSourceIsDead(self, event): + if AXObject.is_dead(event.source): + tokens = ["EVENT MANAGER: source of", event.type, "is dead"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def _ignoreDuringDeluge(self, event): + """Returns true if this event should be ignored during a deluge.""" + + if self._eventSourceIsDead(event): + return True + + ignore = ["object:text-changed:delete", + "object:text-changed:insert", + "object:text-changed:delete:system", + "object:text-changed:insert:system", + "object:text-attributes-changed", + "object:text-caret-moved", + "object:children-changed:add", + "object:children-changed:add:system", + "object:children-changed:remove", + "object:children-changed:remove:system", + "object:property-change:accessible-name", + "object:property-change:accessible-description", + "object:selection-changed", + "object:state-changed:showing", + "object:state-changed:sensitive"] + + if event.type not in ignore: + return False + + return event.source != cthulhu_state.locusOfFocus + + def _inDeluge(self): + size = self._eventQueue.qsize() + if size > 100: + msg = f"EVENT MANAGER: DELUGE! Queue size is {size}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def _processDuringFlood(self, event): + """Returns true if this event should be processed during a flood.""" + + if self._eventSourceIsDead(event): + return False + + ignore = ["object:text-changed:delete", + "object:text-changed:insert", + "object:text-changed:delete:system", + "object:text-changed:insert:system", + "object:text-attributes-changed", + "object:text-caret-moved", + "object:children-changed:add", + "object:children-changed:add:system", + "object:children-changed:remove", + "object:children-changed:remove:system", + "object:property-change:accessible-name", + "object:property-change:accessible-description", + "object:selection-changed", + "object:state-changed:showing", + "object:state-changed:sensitive"] + + if event.type not in ignore: + return True + + return event.source == cthulhu_state.locusOfFocus + + def _prioritizeDuringFlood(self, event): + """Returns true if this event should be prioritized during a flood.""" + + if event.type.startswith("object:state-changed:focused"): + return event.detail1 + + if event.type.startswith("object:state-changed:selected"): + return event.detail1 + + if event.type.startswith("object:text-selection-changed"): + return True + + if event.type.startswith("window:activate"): + return True + + if event.type.startswith("window:deactivate"): + return True + + if event.type.startswith("object:state-changed:active"): + return AXUtilities.is_frame(event.source) or AXUtilities.is_window(event.source) + + if event.type.startswith("document:load-complete"): + return True + + if event.type.startswith("object:state-changed:busy"): + return True + + return False + + def _pruneEventsDuringFlood(self): + """Gets rid of events we don't care about during a flood.""" + + oldSize = self._eventQueue.qsize() + + newQueue = queue.Queue(0) + while not self._eventQueue.empty(): + try: + event = self._eventQueue.get() + except Exception: + continue + + if self._processDuringFlood(event): + newQueue.put(event) + self._queuePrintln(event, isPrune=False) + self._eventQueue.task_done() + + self._eventQueue = newQueue + newSize = self._eventQueue.qsize() + + msg = f"EVENT MANAGER: {oldSize - newSize} events pruned. New size: {newSize}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _inFlood(self): + size = self._eventQueue.qsize() + if size > 50: + msg = f"EVENT MANAGER: FLOOD? Queue size is {size}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def _processObjectEvent(self, event): + """Handles all object events destined for scripts. + + Arguments: + - e: an at-spi event. + """ + + debug.printObjectEvent(debug.LEVEL_INFO, event, timestamp=True) + eType = event.type + + if eType.startswith("object:children-changed:remove") \ + and event.source == AXUtilities.get_desktop(): + _scriptManager.reclaimScripts() + return + + if eType.startswith("window:") and not eType.endswith("create"): + _scriptManager.reclaimScripts() + elif eType.startswith("object:state-changed:active") \ + and AXUtilities.is_frame(event.source): + _scriptManager.reclaimScripts() + + if AXObject.is_dead(event.source) or AXUtilities.is_defunct(event.source): + tokens = ["EVENT MANAGER: Ignoring defunct object:", event.source] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if eType.startswith("window:deactivate") or eType.startswith("window:destroy") \ + and cthulhu_state.activeWindow == event.source: + msg = 'EVENT MANAGER: Clearing active window, script, and locus of focus' + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu_state.locusOfFocus = None + cthulhu_state.activeWindow = None + _scriptManager.setActiveScript(None, "Active window is dead or defunct") + return + + if AXUtilities.is_iconified(event.source): + tokens = ["EVENT MANAGER: Ignoring iconified object:", event.source] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if self._inFlood(): + if not self._processDuringFlood(event): + msg = 'EVENT MANAGER: Not processing this event due to flood.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + if self._prioritizeDuringFlood(event): + msg = 'EVENT MANAGER: Pruning event queue due to flood.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._pruneEventsDuringFlood() + + if eType.startswith('object:selection-changed') \ + and event.source in self._parentsOfDefunctDescendants: + msg = 'EVENT MANAGER: Ignoring event from parent of defunct descendants' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not debug.eventDebugFilter or debug.eventDebugFilter.match(eType) \ + and not eType.startswith("mouse:"): + indent = " " * 32 + debug.printDetails(debug.LEVEL_INFO, indent, event.source) + if isinstance(event.any_data, Atspi.Accessible): + debug.printMessage(debug.LEVEL_INFO, f"{indent}ANY DATA:") + debug.printDetails(debug.LEVEL_INFO, indent, event.any_data, includeApp=False) + + script = self._getScriptForEvent(event) + if not script: + msg = "ERROR: Could not get script for event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + setNewActiveScript, reason = self._isActivatableEvent(event, script) + msg = f'EVENT MANAGER: Change active script: {setNewActiveScript} ({reason})' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if setNewActiveScript: + try: + _scriptManager.setActiveScript(script, reason) + except Exception as error: + tokens = ["EVENT MANAGER: Exception setting active script for", + event.source, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + try: + script.processObjectEvent(event) + except Exception as error: + msg = f"EVENT MANAGER: Exception processing {event.type}: {error}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + debug.printException(debug.LEVEL_INFO) + + tokens = ["EVENT MANAGER: locusOfFocus:", cthulhu_state.locusOfFocus, + "activeScript:", cthulhu_state.activeScript] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if debug.LEVEL_INFO >= debug.debugLevel and cthulhu_state.activeScript: + attributes = cthulhu_state.activeScript.getTransferableAttributes() + for key, value in attributes.items(): + msg = f"EVENT MANAGER: {key}: {value}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _processNewKeyboardEvent(self, device, pressed, keycode, keysym, state, text): + """Process keyboard event using new direct KeyboardEvent creation.""" + + if not pressed and text == "Num_Lock" and "KP_Insert" in settings.cthulhuModifierKeys \ + and cthulhu_state.activeScript is not None: + cthulhu_state.activeScript.refreshKeyGrabs() + + if pressed: + cthulhu_state.openingDialog = (text == "space" \ + and (state & ~(1 << Atspi.ModifierType.NUMLOCK))) + + # Create KeyboardEvent directly with new constructor + keyboardEvent = input_event.KeyboardEvent(pressed, keycode, keysym, state, text or "") + + # Set context information + keyboardEvent.setWindow(cthulhu_state.activeWindow) + keyboardEvent.setObject(cthulhu_state.locusOfFocus) + keyboardEvent.setScript(cthulhu_state.activeScript) + + # Finalize initialization now that context is set + keyboardEvent._finalize_initialization() + + if not keyboardEvent.is_duplicate: + debug.printMessage(debug.LEVEL_INFO, f"\n{keyboardEvent}") + + rv = keyboardEvent.process() + + # Do any needed xmodmap crap. Hopefully this can die soon. + from cthulhu import cthulhu + cthulhu.updateKeyMap(keyboardEvent) + + return rv + + def _processKeyboardEvent(self, event): + # Convert AT-SPI event to new KeyboardEvent format + pressed = event.type == Atspi.EventType.KEY_PRESSED_EVENT + keyboardEvent = input_event.KeyboardEvent(pressed, event.hw_code, event.id, event.modifiers, event.event_string or "") + + # Set context information + keyboardEvent.setWindow(cthulhu_state.activeWindow) + keyboardEvent.setObject(cthulhu_state.locusOfFocus) + keyboardEvent.setScript(cthulhu_state.activeScript) + + # Finalize initialization + keyboardEvent._finalize_initialization() + + if not keyboardEvent.is_duplicate: + debug.printMessage(debug.LEVEL_INFO, f"\n{keyboardEvent}") + + rv = keyboardEvent.process() + + # Do any needed xmodmap crap. Hopefully this can die soon. + from cthulhu import cthulhu + cthulhu.updateKeyMap(keyboardEvent) + + return rv + + def processBrailleEvent(self, brailleEvent): + """Called whenever a cursor key is pressed on the Braille display. + + Arguments: + - brailleEvent: an instance of input_event.BrailleEvent + + Returns True if the command was consumed; otherwise False + """ + + if cthulhu_state.activeScript \ + and cthulhu_state.activeScript.consumesBrailleEvent(brailleEvent): + self._enqueue(brailleEvent) + return True + else: + return False + +_manager = EventManager() + +def getManager(): + return _manager diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/find.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/find.py new file mode 100644 index 0000000..5e567a1 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/find.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides support for a flat review find.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc." \ + "Copyright (c) 2022 Igalia, S.L." +__license__ = "LGPL" + + +import copy +import re + +from . import debug +from . import messages +from . import cthulhu_state + +from .flat_review import Context + + +class _SearchQueryMatch: + """Represents a SearchQuery match.""" + + def __init__(self, context, pattern): + self._line = context.lineIndex + self._zone = context.zoneIndex + self._word = context.wordIndex + self._char = context.charIndex + self._pattern = pattern + self._lineString = context.getCurrent(Context.LINE)[0] + + def __str__(self): + return "SEARCH QUERY MATCH: '%s' (line %i, zone %i, word %i, char %i) for '%s'" % \ + (self._lineString, self._line, self._zone, self._word, self._char, self._pattern) + + def __eq__(self, other): + if not other: + return False + + return self._lineString == other._lineString and \ + self._line == other._line and \ + self._zone == other._zone and \ + self._word == other._word and \ + self._char == other._char + +class SearchQuery: + """Represents a search that the user wants to perform.""" + + def __init__(self): + """Creates a new SearchQuery. A searchQuery has the following + properties: + + searchString - the string to find + searchBackwards - if true, search upward for matches + caseSensitive - if true, case counts + matchEntireWord - if true, only match on the entire string + startAtTop - if true, begin the search from the top of + the window, rather than at the current + location + windowWrap - if true, when the top/bottom edge of the + window is reached wrap to the bottom/top + and continue searching + """ + + self.searchString = "" + self.searchBackwards = False + self.caseSensitive = False + self.matchEntireWord = False + self.windowWrap = False + self.startAtTop = False + self.debugLevel = debug.LEVEL_INFO + self._contextLocation = [0, 0, 0, 0] + self._match = None + self._wrapped = False + + def __str__(self): + string = f"FIND QUERY: '{self.searchString}'." + options = [] + if self.searchBackwards: + options.append("search backwards") + if self.caseSensitive: + options.append("case sensitive") + if self.matchEntireWord: + options.append("match entire word") + if self.windowWrap: + options.append("wrap") + if self.startAtTop: + options.append("start at top") + if options: + string += f" Options: {', '.join(options)}" + if self._match: + string += f" Last match: {self._match}" + return string + + def previousMatch(self): + if not cthulhu_state.searchQuery: + return None + return cthulhu_state.searchQuery._match + + def _saveContextLocation(self, context): + self._contextLocation = [context.lineIndex, + context.zoneIndex, + context.wordIndex, + context.charIndex] + + def _restoreContextLocation(self, context): + context.setCurrent(*self._contextLocation) + self._contextLocation = [0, 0, 0, 0] + + def _currentContextMatches(self, context, pattern, contextType): + if contextType == Context.LINE: + typeString = "LINE" + elif contextType == Context.ZONE: + typeString = "ZONE" + elif contextType == Context.WORD: + typeString = "WORD" + else: + return False + + string = context.getCurrent(contextType)[0] + match = re.search(pattern, string) + msg = "FIND: %s='%s'. Match: %s" % (typeString, string.replace("\n", "\\n"), match) + debug.println(self.debugLevel, msg, True) + return bool(match) + + def _move(self, context, contextType): + if contextType == Context.WORD: + if self.searchBackwards: + return context.goPrevious(Context.WORD, Context.WRAP_LINE) + return context.goNext(Context.WORD, Context.WRAP_LINE) + + if contextType == Context.ZONE: + if self.searchBackwards: + moved = context.goPrevious(Context.ZONE, Context.WRAP_LINE) + context.goEnd(Context.ZONE) + return moved + return context.goNext(Context.ZONE, Context.WRAP_LINE) + + if contextType == Context.LINE: + if self.searchBackwards: + moved = context.goPrevious(Context.LINE, Context.WRAP_LINE) + context.goEnd(Context.LINE) + else: + moved = context.goNext(Context.LINE, Context.WRAP_LINE) + if moved: + return True + if not self.windowWrap or self._wrapped: + return False + self._wrapped = True + if self.searchBackwards: + cthulhu_state.activeScript.presentMessage(messages.WRAPPING_TO_BOTTOM) + moved = context.goPrevious(Context.LINE, Context.WRAP_ALL) + else: + cthulhu_state.activeScript.presentMessage(messages.WRAPPING_TO_TOP) + moved = context.goNext(Context.LINE, Context.WRAP_ALL) + return moved + + return False + + def _findMatchIn(self, context, pattern, contextType): + found = self._currentContextMatches(context, pattern, contextType) + while not found: + if not self._move(context, contextType): + break + found = self._currentContextMatches(context, pattern, contextType) + + return found + + def _findMatch(self, context, pattern): + if not self._findMatchIn(context, pattern, Context.LINE): + return False + + if not self._findMatchIn(context, pattern, Context.ZONE): + return False + + if not self._findMatchIn(context, pattern, Context.WORD): + return False + + if not self.previousMatch(): + return True + + candidateMatch = _SearchQueryMatch(context, pattern) + if candidateMatch != self.previousMatch(): + return True + + if self._move(context, Context.WORD) \ + and self._findMatchIn(context, pattern, Context.WORD): + return True + + if self._move(context, Context.ZONE) \ + and self._findMatchIn(context, pattern, Context.ZONE): + return True + + if self._move(context, Context.LINE): + return self._findMatch(context, pattern) + + return False + + def findQuery(self, context): + """Performs a search on the string specified in searchQuery. + + Arguments: + - context: The context from active script + + Returns: + - The context of the match, if found + """ + + debug.println(self.debugLevel, str(self), True) + flags = re.U + if not self.caseSensitive: + flags = flags | re.IGNORECASE + if self.matchEntireWord: + regexp = "\\b" + self.searchString + "\\b" + else: + regexp = self.searchString + pattern = re.compile(regexp, flags) + + self._saveContextLocation(context) + if self.startAtTop: + context.goBegin(Context.WINDOW) + + location = None + if self._findMatch(context, pattern): + self._saveContextLocation(context) + self._match = _SearchQueryMatch(context, pattern) + self._wrapped = False + location = copy.copy(context) + else: + self._restoreContextLocation(context) + cthulhu_state.searchQuery = copy.copy(self) + return location + +def getLastQuery(): + """Grabs the last search query performed from cthulhu_state. + + Returns: + - A copy of the last search query, if it exists + """ + + lastQuery = copy.copy(cthulhu_state.searchQuery) + return lastQuery diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review.py new file mode 100644 index 0000000..aecc0ce --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review.py @@ -0,0 +1,1437 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides the default implementation for flat review for Cthulhu.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +import re + +from . import braille +from . import debug +from . import cthulhu +from . import cthulhu_state +from . import settings +from .ax_event_synthesizer import AXEventSynthesizer +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +EMBEDDED_OBJECT_CHARACTER = '\ufffc' + +class Char: + """A character's worth of presentable information.""" + + def __init__(self, word, index, startOffset, string, x, y, width, height): + """Creates a new char. + + Arguments: + - word: the Word instance this belongs to + - startOffset: the start offset with respect to the accessible + - string: the actual char + - x, y, width, height: the extents of this Char on the screen + """ + + self.word = word + self.index = index + self.startOffset = startOffset + self.endOffset = startOffset + 1 + self.string = string + self.x = x + self.y = y + self.width = width + self.height = height + + +class Word: + """A single chunk (word or object) of presentable information.""" + + def __init__(self, zone, index, startOffset, string, x, y, width, height): + """Creates a new Word. + + Arguments: + - zone: the Zone instance this belongs to + - index: the index of this Word in the Zone + - startOffset: the start offset with respect to the accessible + - string: the actual string + - x, y, width, height: the extents of this Word on the screen + """ + + self.zone = zone + self.index = index + self.startOffset = startOffset + self.string = string + self.length = len(string) + self.endOffset = self.startOffset + len(string) + self.x = x + self.y = y + self.width = width + self.height = height + self.chars = [] + + def __str__(self): + return "WORD: '%s' (%i-%i) %s" % \ + (self.string.replace("\n", "\\n"), + self.startOffset, + self.endOffset, + self.zone.accessible) + + def __getattribute__(self, attr): + if attr != "chars": + return super().__getattribute__(attr) + + # TODO - JD: For now, don't fake character and word extents. + # The main goal is to improve reviewability. + extents = self.x, self.y, self.width, self.height + + try: + text = self.zone.accessible.queryText() + except Exception: + text = None + + chars = [] + for i, char in enumerate(self.string): + start = i + self.startOffset + if text: + try: + extents = text.getRangeExtents(start, start+1, Atspi.CoordType.SCREEN) + except Exception as error: + tokens = ["FLAT REVIEW: Exception in getRangeExtents:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + chars.append(Char(self, i, start, char, *extents)) + + return chars + + def getRelativeOffset(self, offset): + """Returns the char offset with respect to this word or -1.""" + + if self.startOffset <= offset < self.startOffset + len(self.string): + return offset - self.startOffset + + return -1 + + +class Zone: + """Represents text that is a portion of a single horizontal line.""" + + WORDS_RE = re.compile(r"(\S+\s*)", re.UNICODE) + + def __init__(self, accessible, string, x, y, width, height, role=None): + """Creates a new Zone. + + Arguments: + - accessible: the Accessible associated with this Zone + - string: the string being displayed for this Zone + - extents: x, y, width, height in screen coordinates + - role: Role to override accessible's role. + """ + + self.accessible = accessible + self.startOffset = 0 + self._string = string + self.length = len(string) + self.x = x + self.y = y + self.width = width + self.height = height + self.role = role or AXObject.get_role(accessible) + self._words = [] + + def __str__(self): + return "ZONE: '%s' %s" % (self._string.replace("\n", "\\n"), self.accessible) + + def __getattribute__(self, attr): + """To ensure we update the content.""" + + if attr not in ["words", "string"]: + return super().__getattribute__(attr) + + if attr == "string": + return self._string + + if not self._shouldFakeText(): + return self._words + + # TODO - JD: For now, don't fake character and word extents. + # The main goal is to improve reviewability. + extents = self.x, self.y, self.width, self.height + + words = [] + for i, word in enumerate(re.finditer(self.WORDS_RE, self._string)): + words.append(Word(self, i, word.start(), word.group(), *extents)) + + self._words = words + return words + + def _shouldFakeText(self): + """Returns True if we should try to fake the text interface""" + + textRoles = [Atspi.Role.LABEL, + Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.PAGE_TAB, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.TABLE_CELL] + + if self.role in textRoles: + return True + + return False + + def _extentsAreOnSameLine(self, zone, pixelDelta=5): + """Returns True if this Zone is physically on the same line as zone.""" + + if self.width == 0 and self.height == 0: + return zone.y <= self.y <= zone.y + zone.height + + if zone.width == 0 and self.height == 0: + return self.y <= zone.y <= self.y + self.height + + highestBottom = min(self.y + self.height, zone.y + zone.height) + lowestTop = max(self.y, zone.y) + if lowestTop >= highestBottom: + return False + + middle = self.y + self.height / 2 + zoneMiddle = zone.y + zone.height / 2 + if abs(middle - zoneMiddle) > pixelDelta: + return False + + return True + + def onSameLine(self, zone): + """Returns True if we treat this Zone and zone as being on one line.""" + + if Atspi.Role.SCROLL_BAR in [self.role, zone.role]: + return self.accessible == zone.accessible + + thisParent = AXObject.get_parent(self.accessible) + thisParentRole = AXObject.get_role(thisParent) + zoneParent = AXObject.get_parent(zone.accessible) + zoneParentRole = AXObject.get_role(zoneParent) + if Atspi.Role.MENU_BAR in [thisParentRole, zoneParentRole]: + return thisParent == zoneParent + + return self._extentsAreOnSameLine(zone) + + def getWordAtOffset(self, charOffset): + msg = f"FLAT REVIEW: Searching for word at offset {charOffset}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + for word in self.words: + tokens = ["FLAT REVIEW: Checking", word] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + offset = word.getRelativeOffset(charOffset) + if offset >= 0: + return word, offset + + if self.length == charOffset and self.words: + lastWord = self.words[-1] + return lastWord, lastWord.length + + return None, -1 + + def hasCaret(self): + """Returns True if this Zone contains the caret.""" + + return False + + def wordWithCaret(self): + """Returns the Word and relative offset with the caret.""" + + return None, -1 + +class TextZone(Zone): + """A Zone whose purpose is to display text of an object.""" + + def __init__(self, accessible, startOffset, string, x, y, width, height, role=None): + super().__init__(accessible, string, x, y, width, height, role) + + self.startOffset = startOffset + self.endOffset = self.startOffset + len(string) + self._itext = self.accessible.queryText() + + def __getattribute__(self, attr): + """To ensure we update the content.""" + + if attr not in ["words", "string"]: + return super().__getattribute__(attr) + + string = self._itext.getText(self.startOffset, self.endOffset) + words = [] + for i, word in enumerate(re.finditer(self.WORDS_RE, string)): + start, end = map(lambda x: x + self.startOffset, word.span()) + extents = self._itext.getRangeExtents(start, end, Atspi.CoordType.SCREEN) + words.append(Word(self, i, start, word.group(), *extents)) + + self._string = string + self._words = words + return super().__getattribute__(attr) + + def hasCaret(self): + """Returns True if this Zone contains the caret.""" + + offset = self._itext.caretOffset + if self.startOffset <= offset < self.endOffset: + return True + + return self.endOffset == self._itext.characterCount + + def wordWithCaret(self): + """Returns the Word and relative offset with the caret.""" + + if not self.hasCaret(): + return None, -1 + + return self.getWordAtOffset(self._itext.caretOffset) + + +class StateZone(Zone): + """A Zone whose purpose is to display the state of an object.""" + + def __init__(self, accessible, x, y, width, height, role=None): + super().__init__(accessible, "", x, y, width, height, role) + + def __getattribute__(self, attr): + """To ensure we update the state.""" + + if attr not in ["string", "brailleString"]: + return super().__getattribute__(attr) + + if attr == "string": + generator = cthulhu_state.activeScript.speechGenerator + else: + generator = cthulhu_state.activeScript.brailleGenerator + + result = generator.getStateIndicator(self.accessible, role=self.role) + if result: + return result[0] + + return "" + + +class ValueZone(Zone): + """A Zone whose purpose is to display the value of an object.""" + + def __init__(self, accessible, x, y, width, height, role=None): + super().__init__(accessible, "", x, y, width, height, role) + + def __getattribute__(self, attr): + """To ensure we update the value.""" + + if attr not in ["string", "brailleString"]: + return super().__getattribute__(attr) + + if attr == "string": + generator = cthulhu_state.activeScript.speechGenerator + else: + generator = cthulhu_state.activeScript.brailleGenerator + + result = "" + + # TODO - JD: This cobbling together beats what we had, but the + # generators should also be doing the assembly. + rolename = generator.getLocalizedRoleName(self.accessible) + value = generator.getValue(self.accessible) + if rolename and value: + result = f"{rolename} {value[0]}" + + return result + + +class Line: + """A Line is a single line across a window and is composed of Zones.""" + + def __init__(self, + index, + zones): + """Creates a new Line, which is a horizontal region of text. + + Arguments: + - index: the index of this Line in the window + - zones: the Zones that make up this line + """ + self.index = index + self.zones = zones + self.brailleRegions = None + + def __getattribute__(self, attr): + if attr == "string": + return " ".join([zone.string for zone in self.zones]) + + if attr == "x": + return min([zone.x for zone in self.zones]) + + if attr == "y": + return min([zone.y for zone in self.zones]) + + if attr == "width": + return sum([zone.width for zone in self.zones]) + + if attr == "height": + return max([zone.height for zone in self.zones]) + + return super().__getattribute__(attr) + + def getBrailleRegions(self): + # [[[WDW - We'll always compute the braille regions. This + # allows us to handle StateZone and ValueZone zones whose + # states might be changing on us.]]] + # + if True or not self.brailleRegions: + self.brailleRegions = [] + brailleOffset = 0 + for zone in self.zones: + # The 'isinstance(zone, TextZone)' test is a sanity check + # to handle problems with Java text. See Bug 435553. + if isinstance(zone, TextZone) and \ + ((AXObject.get_role(zone.accessible) in \ + (Atspi.Role.TEXT, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.TERMINAL)) or \ + # [[[TODO: Eitan - HACK: + # This is just to get FF3 cursor key routing support. + # We really should not be determining all this stuff here, + # it should be in the scripts. + # Same applies to roles above.]]] + (AXObject.get_role(zone.accessible) in \ + (Atspi.Role.PARAGRAPH, + Atspi.Role.HEADING, + Atspi.Role.LINK))): + region = braille.ReviewText(zone.accessible, + zone.string, + zone.startOffset, + zone) + else: + try: + brailleString = zone.brailleString + except Exception: + brailleString = zone.string + region = braille.ReviewComponent(zone.accessible, + brailleString, + 0, # cursor offset + zone) + if len(self.brailleRegions): + pad = braille.Region(" ") + pad.brailleOffset = brailleOffset + self.brailleRegions.append(pad) + brailleOffset += 1 + + zone.brailleRegion = region + region.brailleOffset = brailleOffset + self.brailleRegions.append(region) + + regionString = region.string + brailleOffset += len(regionString) + + if not settings.disableBrailleEOL: + if len(self.brailleRegions): + pad = braille.Region(" ") + pad.brailleOffset = brailleOffset + self.brailleRegions.append(pad) + brailleOffset += 1 + eol = braille.Region("$l") + eol.brailleOffset = brailleOffset + self.brailleRegions.append(eol) + + return self.brailleRegions + +class Context: + """Contains the flat review regions for the current top-level object.""" + + ZONE = 0 + CHAR = 1 + WORD = 2 + LINE = 3 # includes all zones on same line + WINDOW = 4 + + WRAP_NONE = 0 + WRAP_LINE = 1 << 0 + WRAP_TOP_BOTTOM = 1 << 1 + WRAP_ALL = (WRAP_LINE | WRAP_TOP_BOTTOM) + + def __init__(self, script, root=None): + """Create a new Context for script.""" + + self.script = script + self.zones = [] + self.lines = [] + self.lineIndex = 0 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + self.targetCharInfo = None + self.focusZone = None + self.container = None + self.focusObj = cthulhu.getActiveModeAndObjectOfInterest()[1] or cthulhu_state.locusOfFocus + self.topLevel = None + self.bounds = 0, 0, 0, 0 + + frame, dialog = script.utilities.frameAndDialog(self.focusObj) + if root is not None: + self.topLevel = root + tokens = ["FLAT REVIEW: Restricting flat review to", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + self.topLevel = dialog or frame + tokens = ["FLAT REVIEW: Frame:", frame, "Dialog:", dialog, ". Top level:", self.topLevel] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + try: + component = self.topLevel.queryComponent() + self.bounds = component.getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["ERROR: Exception getting extents of", self.topLevel] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + containerRoles = [Atspi.Role.MENU] + + def isContainer(x): + return AXObject.get_role(x) in containerRoles + + container = AXObject.find_ancestor(self.focusObj, isContainer) + if not container and isContainer(self.focusObj): + container = self.focusObj + + self.container = container or self.topLevel + + self.zones, self.focusZone = self.getShowingZones(self.container) + self.lines = self.clusterZonesByLine(self.zones) + if not (self.lines and self.focusZone): + return + + for i, line in enumerate(self.lines): + if self.focusZone in line.zones: + self.lineIndex = i + self.zoneIndex = line.zones.index(self.focusZone) + word, offset = self.focusZone.wordWithCaret() + if word: + self.wordIndex = word.index + self.charIndex = offset + break + + msg = ( + f"FLAT REVIEW: On line {self.lineIndex}, zone {self.zoneIndex} " + f"word {self.wordIndex}, char {self.charIndex}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def splitTextIntoZones(self, accessible, string, startOffset, cliprect): + """Traverses the string, splitting it up into separate zones if the + string contains the EMBEDDED_OBJECT_CHARACTER, which is used by apps + such as Firefox to handle containment of things such as links in + paragraphs. + + Arguments: + - accessible: the accessible + - string: a substring from the accessible's text specialization + - startOffset: the starting character offset of the string + - cliprect: the extents that the Zones must fit inside. + + Returns a list of Zones for the visible text. + """ + + zones = [] + substrings = [(*m.span(), m.group(0)) for m in re.finditer(r"[^\ufffc]+", string)] + substrings = list(map(lambda x: (x[0] + startOffset, x[1] + startOffset, x[2]), substrings)) + for (start, end, substring) in substrings: + extents = accessible.queryText().getRangeExtents(start, end, Atspi.CoordType.SCREEN) + if self.script.utilities.containsRegion(extents, cliprect): + clipping = self.script.utilities.intersection(extents, cliprect) + zones.append(TextZone(accessible, start, substring, *clipping)) + + return zones + + def _getLines(self, accessible, startOffset, endOffset): + # TODO - JD: Move this into the script utilities so we can better handle + # app and toolkit quirks and also reuse this (e.g. for SayAll). + try: + text = accessible.queryText() + except NotImplementedError: + return [] + + lines = [] + offset = startOffset + while offset < min(endOffset, text.characterCount): + result = text.getTextAtOffset(offset, Atspi.TextBoundaryType.LINE_START) + if result[0] and result not in lines: + lines.append(result) + offset = max(result[2], offset + 1) + + return lines + + def getZonesFromText(self, accessible, cliprect): + """Gets a list of Zones from an object that implements the + AccessibleText specialization. + + Arguments: + - accessible: the accessible + - cliprect: the extents that the Zones must fit inside. + + Returns a list of Zones. + """ + + if not self.script.utilities.hasPresentableText(accessible): + return [] + + zones = [] + text = accessible.queryText() + + # TODO - JD: This is here temporarily whilst I sort out the rest + # of the text-related mess. + if AXObject.supports_editable_text(accessible) \ + and AXUtilities.is_single_line(accessible): + extents = accessible.queryComponent().getExtents(0) + return [TextZone(accessible, 0, text.getText(0, -1), *extents)] + + upperMax = lowerMax = text.characterCount + upperMid = lowerMid = int(upperMax / 2) + upperMin = lowerMin = 0 + oldMid = 0 + + # performing binary search to locate first line inside clipped area + while oldMid != upperMid: + oldMid = upperMid + [x, y, width, height] = text.getRangeExtents(upperMid, + upperMid+1, + 0) + if y > cliprect.y: + upperMax = upperMid + else: + upperMin = upperMid + upperMid = int((upperMax - upperMin) / 2) + upperMin + + # performing binary search to locate last line inside clipped area + oldMid = 0 + limit = cliprect.y+cliprect.height + while oldMid != lowerMid: + oldMid = lowerMid + [x, y, width, height] = text.getRangeExtents(lowerMid, + lowerMid+1, + 0) + if y > limit: + lowerMax = lowerMid + else: + lowerMin = lowerMid + lowerMid = int((lowerMax - lowerMin) / 2) + lowerMin + + msg = "FLAT REVIEW: Getting lines for %s offsets %i-%i" % (accessible, upperMin, lowerMax) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + lines = self._getLines(accessible, upperMin, lowerMax) + tokens = ["FLAT REVIEW:", len(lines), "lines found for", accessible] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + for string, startOffset, endOffset in lines: + zones.extend(self.splitTextIntoZones(accessible, string, startOffset, cliprect)) + + return zones + + def _insertStateZone(self, zones, accessible, extents): + """If the accessible presents non-textual state, such as a + checkbox or radio button, insert a StateZone representing + that state.""" + + # TODO - JD: This whole thing is pretty hacky. Either do it + # right or nuke it. + + indicatorExtents = [extents.x, extents.y, 1, extents.height] + role = AXObject.get_role(accessible) + if role == Atspi.Role.TOGGLE_BUTTON: + zone = StateZone(accessible, *indicatorExtents, role=role) + if zone: + zones.insert(0, zone) + return + + if role == Atspi.Role.TABLE_CELL \ + and self.script.utilities.hasMeaningfulToggleAction(accessible): + role = Atspi.Role.CHECK_BOX + + if role not in [Atspi.Role.CHECK_BOX, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.RADIO_MENU_ITEM]: + return + + zone = None + stateOnLeft = True + + if len(zones) == 1 and isinstance(zones[0], TextZone): + textZone = zones[0] + textToLeftEdge = textZone.x - extents.x + textToRightEdge = (extents.x + extents.width) - (textZone.x + textZone.width) + stateOnLeft = textToLeftEdge > 20 + if stateOnLeft: + indicatorExtents[2] = textToLeftEdge + else: + indicatorExtents[0] = textZone.x + textZone.width + indicatorExtents[2] = textToRightEdge + + zone = StateZone(accessible, *indicatorExtents, role=role) + if zone: + if stateOnLeft: + zones.insert(0, zone) + else: + zones.append(zone) + + def getZonesFromAccessible(self, accessible, cliprect): + """Returns a list of Zones for the given accessible.""" + + try: + component = accessible.queryComponent() + extents = component.getExtents(Atspi.CoordType.SCREEN) + except Exception: + return [] + + try: + role = AXObject.get_role(accessible) + except Exception: + return [] + + zones = self.getZonesFromText(accessible, cliprect) + if not zones and role in [Atspi.Role.SCROLL_BAR, + Atspi.Role.SLIDER, + Atspi.Role.PROGRESS_BAR]: + zones.append(ValueZone(accessible, *extents)) + elif not zones: + string = "" + redundant = [Atspi.Role.TABLE_ROW] + if role not in redundant: + string = self.script.speechGenerator.getName(accessible, inFlatReview=True) + + useless = [Atspi.Role.TABLE_CELL, Atspi.Role.LABEL] + if not string and role not in useless: + string = self.script.speechGenerator.getRoleName(accessible) + if string: + zones.append(Zone(accessible, string, *extents)) + + self._insertStateZone(zones, accessible, extents) + + return zones + + def _isOrIsIn(self, child, parent): + if not (child and parent): + return False + + if child == parent: + return True + + return AXObject.find_ancestor(child, lambda x: x == parent) + + def setCurrentToZoneWithObject(self, obj): + """Attempts to set the current zone to obj, if obj is in the current context.""" + + tokens = ["FLAT REVIEW: Current", self.getCurrentAccessible(), + f"line: {self.lineIndex}, zone: {self.zoneIndex},", + f"word: {self.wordIndex}, char: {self.charIndex})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + zone = self._findZoneWithObject(obj) + tokens = ["FLAT REVIEW: Zone with", obj, "is", zone] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if zone is None: + return False + + for i, line in enumerate(self.lines): + if zone in line.zones: + self.lineIndex = i + self.zoneIndex = line.zones.index(zone) + word, offset = zone.wordWithCaret() + if word: + self.wordIndex = word.index + self.charIndex = offset + msg = "FLAT REVIEW: Updated current zone." + debug.printMessage(debug.LEVEL_INFO, msg, True) + break + else: + msg = "FLAT REVIEW: Failed to update current zone." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + tokens = ["FLAT REVIEW: Updated", self.getCurrentAccessible(), + f"line: {self.lineIndex}, zone: {self.zoneIndex},", + f"word: {self.wordIndex}, char: {self.charIndex})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def _findZoneWithObject(self, obj): + """Returns the existing zone which contains obj.""" + + if obj is None: + return None + + for zone in self.zones: + if zone.accessible == obj: + return zone + + # Some items get pruned from the flat review tree. For instance, a + # tree item which has a descendant section whose text is the displayed + # text of the tree item, that section will be in the flat review tree + # but the ancestor item might not. + if AXObject.is_ancestor(zone.accessible, obj): + tokens = ["FLAT REVIEW:", zone.accessible, "is ancestor of zone accessible", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return zone + + return None + + def getShowingZones(self, root, boundingbox=None): + """Returns an unsorted list of all the zones under root and the focusZone.""" + + if boundingbox is None: + boundingbox = self.bounds + + objs = self.script.utilities.getOnScreenObjects(root, boundingbox) + tokens = ["FLAT REVIEW:", len(objs), "on-screen objects found for", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + allZones, focusZone = [], None + for o in objs: + zones = self.getZonesFromAccessible(o, boundingbox) + if not zones: + descendant = self.script.utilities.realActiveDescendant(o) + if descendant: + zones = self.getZonesFromAccessible(descendant, boundingbox) + + if not zones: + continue + + allZones.extend(zones) + if not focusZone and zones and self.focusObj and self._isOrIsIn(o, self.focusObj): + zones = list(filter(lambda z: z.hasCaret(), zones)) or zones + focusZone = zones[0] + + tokens = ["FLAT REVIEW:", len(allZones), "zones found for", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return allZones, focusZone + + def clusterZonesByLine(self, zones): + """Returns a sorted list of Line clusters containing sorted Zones.""" + + if not zones: + return [] + + lineClusters = [] + sortedZones = sorted(zones, key=lambda z: z.y) + newCluster = [sortedZones.pop(0)] + for zone in sortedZones: + if zone.onSameLine(newCluster[-1]): + newCluster.append(zone) + else: + lineClusters.append(sorted(newCluster, key=lambda z: z.x)) + newCluster = [zone] + + if newCluster: + lineClusters.append(sorted(newCluster, key=lambda z: z.x)) + + lines = [] + for lineIndex, lineCluster in enumerate(lineClusters): + lines.append(Line(lineIndex, lineCluster)) + for zoneIndex, zone in enumerate(lineCluster): + zone.line = lines[lineIndex] + zone.index = zoneIndex + + tokens = ["FLAT REVIEW: Zones clustered into", len(lines), "lines"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return lines + + def getCurrent(self, flatReviewType=ZONE): + """Returns the current string, offset, and extent information.""" + + # TODO - JD: This method has not (yet) been renamed. But we have a + # getter and setter which do totally different things.... + + zone = self._getCurrentZone() + if not zone: + return None, -1, -1, -1, -1 + + current = zone + if flatReviewType == Context.LINE: + current = zone.line + elif flatReviewType != Context.ZONE and zone.words: + current = zone.words[self.wordIndex] + if flatReviewType == Context.CHAR and current.chars: + try: + current = current.chars[self.charIndex] + except Exception: + return None, -1, -1, -1, -1 + + return current.string, current.x, current.y, current.width, current.height + + def setCurrent(self, lineIndex, zoneIndex, wordIndex, charIndex): + """Sets the current character of interest. + + Arguments: + - lineIndex: index into lines + - zoneIndex: index into lines[lineIndex].zones + - wordIndex: index into lines[lineIndex].zones[zoneIndex].words + - charIndex: index lines[lineIndex].zones[zoneIndex].words[wordIndex].chars + """ + + self.lineIndex = lineIndex + self.zoneIndex = zoneIndex + self.wordIndex = wordIndex + self.charIndex = charIndex + self.targetCharInfo = self.getCurrent(Context.CHAR) + + def _getClickPoint(self): + string, x, y, width, height = self.getCurrent(Context.CHAR) + if (x < 0 and y < 0) or (width <= 0 and height <=0): + return -1, -1 + + # Click left of center to position the caret there. + x = int(max(x, x + (width / 2) - 1)) + y = int(y + height / 2) + + return x, y + + def routeToCurrent(self): + """Routes the mouse pointer to the current accessible.""" + + x, y = self._getClickPoint() + if x < 0 or y < 0: + return False + + return AXEventSynthesizer.route_to_point(x, y) + + def clickCurrent(self, button=1): + """Performs a mouse click on the current accessible.""" + + x, y = self._getClickPoint() + if x >= 0 and y >= 0 and AXEventSynthesizer.click_point(x, y, button): + return True + + if AXEventSynthesizer.click_object(self.getCurrentAccessible(), button): + return True + + return False + + def _getCurrentZone(self): + if not (self.lines and 0 <= self.lineIndex < len(self.lines)): + return None + + line = self.lines[self.lineIndex] + if not (line and 0 <= self.zoneIndex < len(line.zones)): + return None + + return line.zones[self.zoneIndex] + + def getCurrentAccessible(self): + """Returns the current accessible.""" + + zone = self._getCurrentZone() + if not zone: + return None + + return zone.accessible + + def getCurrentBrailleRegions(self): + """Gets the braille for the entire current line. + + Returns [regions, regionWithFocus] + """ + + if (not self.lines) \ + or (not self.lines[self.lineIndex].zones): + return [None, None] + + regionWithFocus = None + line = self.lines[self.lineIndex] + regions = line.getBrailleRegions() + + # Now find the current region and the current character offset + # into that region. + # + for zone in line.zones: + if zone.index == self.zoneIndex: + regionWithFocus = zone.brailleRegion + regionWithFocus.cursorOffset = 0 + if zone.words: + regionWithFocus.cursorOffset += zone.words[0].startOffset - zone.startOffset + for wordIndex in range(0, self.wordIndex): + regionWithFocus.cursorOffset += \ + len(zone.words[wordIndex].string) + regionWithFocus.cursorOffset += self.charIndex + regionWithFocus.repositionCursor() + break + + return [regions, regionWithFocus] + + def goBegin(self, flatReviewType=WINDOW): + """Moves this context's locus of interest to the first char + of the first relevant zone. + + Arguments: + - flatReviewType: one of ZONE, LINE or WINDOW + + Returns True if the locus of interest actually changed. + """ + + if (flatReviewType == Context.LINE) or (flatReviewType == Context.ZONE): + lineIndex = self.lineIndex + elif flatReviewType == Context.WINDOW: + lineIndex = 0 + else: + raise Exception("Invalid type: %d" % flatReviewType) + + if flatReviewType == Context.ZONE: + zoneIndex = self.zoneIndex + else: + zoneIndex = 0 + + wordIndex = 0 + charIndex = 0 + + moved = (self.lineIndex != lineIndex) \ + or (self.zoneIndex != zoneIndex) \ + or (self.wordIndex != wordIndex) \ + or (self.charIndex != charIndex) \ + + if moved: + self.lineIndex = lineIndex + self.zoneIndex = zoneIndex + self.wordIndex = wordIndex + self.charIndex = charIndex + self.targetCharInfo = self.getCurrent(Context.CHAR) + + return moved + + def goEnd(self, flatReviewType=WINDOW): + """Moves this context's locus of interest to the last char + of the last relevant zone. + + Arguments: + - flatReviewType: one of ZONE, LINE, or WINDOW + + Returns True if the locus of interest actually changed. + """ + + if (flatReviewType == Context.LINE) or (flatReviewType == Context.ZONE): + lineIndex = self.lineIndex + elif flatReviewType == Context.WINDOW: + lineIndex = len(self.lines) - 1 + else: + raise Exception("Invalid type: %d" % flatReviewType) + + if flatReviewType == Context.ZONE: + zoneIndex = self.zoneIndex + else: + zoneIndex = len(self.lines[lineIndex].zones) - 1 + + zone = self.lines[lineIndex].zones[zoneIndex] + if zone.words: + wordIndex = len(zone.words) - 1 + chars = zone.words[wordIndex].chars + if chars: + charIndex = len(chars) - 1 + else: + charIndex = 0 + else: + wordIndex = 0 + charIndex = 0 + + moved = (self.lineIndex != lineIndex) \ + or (self.zoneIndex != zoneIndex) \ + or (self.wordIndex != wordIndex) \ + or (self.charIndex != charIndex) \ + + if moved: + self.lineIndex = lineIndex + self.zoneIndex = zoneIndex + self.wordIndex = wordIndex + self.charIndex = charIndex + self.targetCharInfo = self.getCurrent(Context.CHAR) + + return moved + + def goPrevious(self, flatReviewType=ZONE, + wrap=WRAP_ALL, omitWhitespace=True): + """Moves this context's locus of interest to the first char + of the previous type. + + Arguments: + - flatReviewType: one of ZONE, CHAR, WORD, LINE + - wrap: if True, will cross boundaries, including top and + bottom; if False, will stop on boundaries. + + Returns True if the locus of interest actually changed. + """ + + if not self.lines: + debug.printMessage(debug.LEVEL_INFO, 'goPrevious(): no lines in context') + return False + + moved = False + + if flatReviewType == Context.ZONE: + if self.zoneIndex > 0: + self.zoneIndex -= 1 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + elif wrap & Context.WRAP_LINE: + if self.lineIndex > 0: + self.lineIndex -= 1 + self.zoneIndex = len(self.lines[self.lineIndex].zones) - 1 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + elif wrap & Context.WRAP_TOP_BOTTOM: + self.lineIndex = len(self.lines) - 1 + self.zoneIndex = len(self.lines[self.lineIndex].zones) - 1 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + elif flatReviewType == Context.CHAR: + if self.charIndex > 0: + self.charIndex -= 1 + moved = True + else: + moved = self.goPrevious(Context.WORD, wrap, False) + if moved: + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + if zone.words: + chars = zone.words[self.wordIndex].chars + if chars: + self.charIndex = len(chars) - 1 + elif flatReviewType == Context.WORD: + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + accessible = zone.accessible + lineIndex = self.lineIndex + zoneIndex = self.zoneIndex + wordIndex = self.wordIndex + charIndex = self.charIndex + + if self.wordIndex > 0: + self.wordIndex -= 1 + self.charIndex = 0 + moved = True + else: + moved = self.goPrevious(Context.ZONE, wrap) + if moved: + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + if zone.words: + self.wordIndex = len(zone.words) - 1 + + # If we landed on a whitespace word or something with no words, + # we might need to move some more. + # + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + if omitWhitespace \ + and moved \ + and ((len(zone.string) == 0) \ + or (len(zone.words) \ + and zone.words[self.wordIndex].string.isspace())): + + hasMoreText = False + if self.lineIndex > 0 and isinstance(zone, TextZone): + prevZone = self.lines[self.lineIndex - 1].zones[-1] + if prevZone.accessible == zone.accessible: + hasMoreText = True + + # If we're on whitespace in the same zone, then let's + # try to move on. If not, we've definitely moved + # across accessibles. If that's the case, let's try + # to find the first 'real' word in the accessible. + # If we cannot, then we're just stuck on an accessible + # with no words and we should do our best to announce + # this to the user (e.g., "whitespace" or "blank"). + # + if zone.accessible == accessible or hasMoreText: + moved = self.goPrevious(Context.WORD, wrap) + else: + wordIndex = self.wordIndex - 1 + while wordIndex >= 0: + if (not zone.words[wordIndex].string) \ + or not len(zone.words[wordIndex].string) \ + or zone.words[wordIndex].string.isspace(): + wordIndex -= 1 + else: + break + if wordIndex >= 0: + self.wordIndex = wordIndex + + if not moved: + self.lineIndex = lineIndex + self.zoneIndex = zoneIndex + self.wordIndex = wordIndex + self.charIndex = charIndex + + elif flatReviewType == Context.LINE: + if wrap & Context.WRAP_LINE: + if self.lineIndex > 0: + self.lineIndex -= 1 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + elif (wrap & Context.WRAP_TOP_BOTTOM) \ + and (len(self.lines) != 1): + self.lineIndex = len(self.lines) - 1 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + else: + raise Exception("Invalid type: %d" % flatReviewType) + + if moved and (flatReviewType != Context.LINE): + self.targetCharInfo = self.getCurrent(Context.CHAR) + + return moved + + def goNext(self, flatReviewType=ZONE, wrap=WRAP_ALL, omitWhitespace=True): + """Moves this context's locus of interest to first char of + the next type. + + Arguments: + - flatReviewType: one of ZONE, CHAR, WORD, LINE + - wrap: if True, will cross boundaries, including top and + bottom; if False, will stop on boundaries. + """ + + if not self.lines: + debug.printMessage(debug.LEVEL_INFO, 'goNext(): no lines in context') + return False + + moved = False + + if flatReviewType == Context.ZONE: + if self.zoneIndex < (len(self.lines[self.lineIndex].zones) - 1): + self.zoneIndex += 1 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + elif wrap & Context.WRAP_LINE: + if self.lineIndex < (len(self.lines) - 1): + self.lineIndex += 1 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + braille.clear() + elif wrap & Context.WRAP_TOP_BOTTOM: + self.lineIndex = 0 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + braille.clear() + elif flatReviewType == Context.CHAR: + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + if zone.words: + chars = zone.words[self.wordIndex].chars + if chars: + if self.charIndex < (len(chars) - 1): + self.charIndex += 1 + moved = True + else: + moved = self.goNext(Context.WORD, wrap, False) + else: + moved = self.goNext(Context.WORD, wrap) + else: + moved = self.goNext(Context.ZONE, wrap) + elif flatReviewType == Context.WORD: + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + accessible = zone.accessible + lineIndex = self.lineIndex + zoneIndex = self.zoneIndex + wordIndex = self.wordIndex + charIndex = self.charIndex + + if zone.words: + if self.wordIndex < (len(zone.words) - 1): + self.wordIndex += 1 + self.charIndex = 0 + moved = True + else: + moved = self.goNext(Context.ZONE, wrap) + else: + moved = self.goNext(Context.ZONE, wrap) + + # If we landed on a whitespace word or something with no words, + # we might need to move some more. + # + zone = self.lines[self.lineIndex].zones[self.zoneIndex] + if omitWhitespace \ + and moved \ + and ((len(zone.string) == 0) \ + or (len(zone.words) \ + and zone.words[self.wordIndex].string.isspace())): + + # If we're on whitespace in the same zone, then let's + # try to move on. If not, we've definitely moved + # across accessibles. If that's the case, let's try + # to find the first 'real' word in the accessible. + # If we cannot, then we're just stuck on an accessible + # with no words and we should do our best to announce + # this to the user (e.g., "whitespace" or "blank"). + # + if zone.accessible == accessible: + moved = self.goNext(Context.WORD, wrap) + else: + wordIndex = self.wordIndex + 1 + while wordIndex < len(zone.words): + if (not zone.words[wordIndex].string) \ + or not len(zone.words[wordIndex].string) \ + or zone.words[wordIndex].string.isspace(): + wordIndex += 1 + else: + break + if wordIndex < len(zone.words): + self.wordIndex = wordIndex + + if not moved: + self.lineIndex = lineIndex + self.zoneIndex = zoneIndex + self.wordIndex = wordIndex + self.charIndex = charIndex + + elif flatReviewType == Context.LINE: + if wrap & Context.WRAP_LINE: + if self.lineIndex < (len(self.lines) - 1): + self.lineIndex += 1 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + elif (wrap & Context.WRAP_TOP_BOTTOM) \ + and (self.lineIndex != 0): + self.lineIndex = 0 + self.zoneIndex = 0 + self.wordIndex = 0 + self.charIndex = 0 + moved = True + else: + raise Exception("Invalid type: %d" % flatReviewType) + + if moved and (flatReviewType != Context.LINE): + self.targetCharInfo = self.getCurrent(Context.CHAR) + + return moved + + def goAbove(self, flatReviewType=LINE, wrap=WRAP_ALL): + """Moves this context's locus of interest to first char + of the type that's closest to and above the current locus of + interest. + + Arguments: + - flatReviewType: LINE + - wrap: if True, will cross top/bottom boundaries; if False, will + stop on top/bottom boundaries. + + Returns: [string, startOffset, endOffset, x, y, width, height] + """ + + moved = False + if flatReviewType == Context.CHAR: + # We want to shoot for the closest character, which we've + # saved away as self.targetCharInfo, which is the list + # [string, x, y, width, height]. + # + if not self.targetCharInfo: + self.targetCharInfo = self.getCurrent(Context.CHAR) + target = self.targetCharInfo + + [string, x, y, width, height] = target + middleTargetX = x + (width / 2) + + moved = self.goPrevious(Context.LINE, wrap) + if moved: + while True: + [string, bx, by, bwidth, bheight] = \ + self.getCurrent(Context.CHAR) + if (bx + width) >= middleTargetX: + break + elif not self.goNext(Context.CHAR, Context.WRAP_NONE): + break + + # Moving around might have reset the current targetCharInfo, + # so we reset it to our saved value. + # + self.targetCharInfo = target + elif flatReviewType == Context.LINE: + return self.goPrevious(flatReviewType, wrap) + else: + raise Exception("Invalid type: %d" % flatReviewType) + + return moved + + def goBelow(self, flatReviewType=LINE, wrap=WRAP_ALL): + """Moves this context's locus of interest to the first + char of the type that's closest to and below the current + locus of interest. + + Arguments: + - flatReviewType: one of WORD, LINE + - wrap: if True, will cross top/bottom boundaries; if False, will + stop on top/bottom boundaries. + + Returns: [string, startOffset, endOffset, x, y, width, height] + """ + + moved = False + if flatReviewType == Context.CHAR: + # We want to shoot for the closest character, which we've + # saved away as self.targetCharInfo, which is the list + # [string, x, y, width, height]. + # + if not self.targetCharInfo: + self.targetCharInfo = self.getCurrent(Context.CHAR) + target = self.targetCharInfo + + [string, x, y, width, height] = target + middleTargetX = x + (width / 2) + + moved = self.goNext(Context.LINE, wrap) + if moved: + while True: + [string, bx, by, bwidth, bheight] = \ + self.getCurrent(Context.CHAR) + if (bx + width) >= middleTargetX: + break + elif not self.goNext(Context.CHAR, Context.WRAP_NONE): + break + + # Moving around might have reset the current targetCharInfo, + # so we reset it to our saved value. + # + self.targetCharInfo = target + elif flatReviewType == Context.LINE: + moved = self.goNext(flatReviewType, wrap) + else: + raise Exception("Invalid type: %d" % flatReviewType) + + return moved diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review_presenter.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review_presenter.py new file mode 100644 index 0000000..aff7c45 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/flat_review_presenter.py @@ -0,0 +1,1193 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for flat-review commands""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2016-2023 Igalia, S.L." +__license__ = "LGPL" + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + +from . import braille +from . import cmdnames +from . import debug +from . import flat_review +from . import guilabels +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu +from . import cthulhu_state +from . import settings_manager +from . import settings + +_settingsManager = settings_manager.getManager() + +class FlatReviewPresenter: + """Provides access to on-screen objects via flat-review.""" + + def __init__(self): + self._context = None + self._current_contents = "" + self._restrict = _settingsManager.getSetting("flatReviewIsRestricted") + self._handlers = self._setup_handlers() + self._desktop_bindings = self._setup_desktop_bindings() + self._laptop_bindings = self._setup_laptop_bindings() + self._gui = None + + def is_active(self): + """Returns True if the flat review presenter is active.""" + + return self._context is not None + + def get_or_create_context(self, script=None): + """Returns the flat review context, creating one if necessary.""" + + # TODO - JD: Scripts should not be able to interact with the + # context directly. get_or_create_context is public temporarily + # to prevent breakage. + + if not self._context: + msg = f"FLAT REVIEW PRESENTER: Creating new context. Restrict: {self._restrict}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if self._restrict: + mode, obj = cthulhu.getActiveModeAndObjectOfInterest() + self._context = flat_review.Context(script, root=obj) + else: + self._context = flat_review.Context(script) + + cthulhu.emitRegionChanged(self._context.getCurrentAccessible(), mode=cthulhu.FLAT_REVIEW) + if script is not None: + script.justEnteredFlatReviewMode = True + script.targetCursorCell = script.getBrailleCursorCell() + return self._context + + msg = f"FLAT REVIEW PRESENTER: Using existing context. Restrict: {self._restrict}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # If we are in unrestricted mode, update the context as below. + # If the context already exists, but the active mode is not flat review, update + # the flat review location to that of the object of interest -- if the object of + # interest is in the flat review context (which means it's on screen). In some + # cases the object of interest will not be in the flat review context because it + # is represented by descendant text objects. setCurrentToZoneWithObject checks + # for this condition and if it can find a zone whose ancestor is the object of + # interest, it will set the current zone to the descendant, causing Cthulhu to + # present the text at the location of the object of interest. + mode, obj = cthulhu.getActiveModeAndObjectOfInterest() + obj = obj or cthulhu_state.locusOfFocus + if mode != cthulhu.FLAT_REVIEW and obj != self._context.getCurrentAccessible() \ + and not self._restrict: + tokens = ["FLAT REVIEW PRESENTER: Attempting to update location from", + self._context.getCurrentAccessible(), "to", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._context.setCurrentToZoneWithObject(obj) + + # If we are restricting, and the current mode is not flat review, calculate a new context + if self._restrict and mode != cthulhu.FLAT_REVIEW: + msg = "FLAT REVIEW PRESENTER: Creating new restricted context." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._context = flat_review.Context(script, obj) + + return self._context + + def get_bindings(self, is_desktop): + """Returns the flat-review-presenter keybindings.""" + + if is_desktop: + return self._desktop_bindings + return self._laptop_bindings + + def get_braille_bindings(self): + """Returns the flat-review-presenter braille bindings.""" + + bindings = {} + try: + bindings[braille.brlapi.KEY_CMD_LNUP] = \ + self._handlers.get("reviewAboveHandler") + bindings[braille.brlapi.KEY_CMD_LNDN] = \ + self._handlers.get("reviewBelowHandler") + bindings[braille.brlapi.KEY_CMD_FREEZE] = \ + self._handlers.get("toggleFlatReviewModeHandler") + bindings[braille.brlapi.KEY_CMD_TOP_LEFT] = \ + self._handlers.get("reviewHomeHandler") + bindings[braille.brlapi.KEY_CMD_BOT_LEFT] = \ + self._handlers.get("reviewBottomLeftHandler") + except Exception as error: + tokens = ["FLAT REVIEW PRESENTER: Exception getting braille bindings:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return {} + return bindings + + def get_handlers(self): + """Returns the flat-review-presenter handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the flat-review-presenter input event handlers.""" + + handlers = {} + + handlers["toggleFlatReviewModeHandler"] = \ + input_event.InputEventHandler( + self.toggle_flat_review_mode, + cmdnames.TOGGLE_FLAT_REVIEW) + + handlers["reviewHomeHandler"] = \ + input_event.InputEventHandler( + self.go_home, + cmdnames.REVIEW_HOME) + + handlers["reviewEndHandler"] = \ + input_event.InputEventHandler( + self.go_end, + cmdnames.REVIEW_END) + + handlers["reviewBottomLeftHandler"] = \ + input_event.InputEventHandler( + self.go_bottom_left, + cmdnames.REVIEW_BOTTOM_LEFT) + + handlers["reviewPreviousLineHandler"] = \ + input_event.InputEventHandler( + self.go_previous_line, + cmdnames.REVIEW_PREVIOUS_LINE) + + handlers["reviewCurrentLineHandler"] = \ + input_event.InputEventHandler( + self.present_line, + cmdnames.REVIEW_CURRENT_LINE) + + handlers["reviewNextLineHandler"] = \ + input_event.InputEventHandler( + self.go_next_line, + cmdnames.REVIEW_NEXT_LINE) + + handlers["reviewSpellCurrentLineHandler"] = \ + input_event.InputEventHandler( + self.spell_line, + cmdnames.REVIEW_SPELL_CURRENT_LINE) + + handlers["reviewPhoneticCurrentLineHandler"] = \ + input_event.InputEventHandler( + self.phonetic_line, + cmdnames.REVIEW_PHONETIC_CURRENT_LINE) + + handlers["reviewEndOfLineHandler"] = \ + input_event.InputEventHandler( + self.go_end_of_line, + cmdnames.REVIEW_END_OF_LINE) + + handlers["reviewPreviousItemHandler"] = \ + input_event.InputEventHandler( + self.go_previous_item, + cmdnames.REVIEW_PREVIOUS_ITEM) + + handlers["reviewCurrentItemHandler"] = \ + input_event.InputEventHandler( + self.present_item, + cmdnames.REVIEW_CURRENT_ITEM) + + handlers["reviewNextItemHandler"] = \ + input_event.InputEventHandler( + self.go_next_item, + cmdnames.REVIEW_NEXT_ITEM) + + handlers["reviewSpellCurrentItemHandler"] = \ + input_event.InputEventHandler( + self.spell_item, + cmdnames.REVIEW_SPELL_CURRENT_ITEM) + + handlers["reviewPhoneticCurrentItemHandler"] = \ + input_event.InputEventHandler( + self.phonetic_item, + cmdnames.REVIEW_PHONETIC_CURRENT_ITEM) + + handlers["reviewPreviousCharacterHandler"] = \ + input_event.InputEventHandler( + self.go_previous_character, + cmdnames.REVIEW_PREVIOUS_CHARACTER) + + handlers["reviewCurrentCharacterHandler"] = \ + input_event.InputEventHandler( + self.present_character, + cmdnames.REVIEW_CURRENT_CHARACTER) + + handlers["reviewSpellCurrentCharacterHandler"] = \ + input_event.InputEventHandler( + self.spell_character, + cmdnames.REVIEW_SPELL_CURRENT_CHARACTER) + + handlers["reviewUnicodeCurrentCharacterHandler"] = \ + input_event.InputEventHandler( + self.unicode_current_character, + cmdnames.REVIEW_UNICODE_CURRENT_CHARACTER) + + handlers["reviewNextCharacterHandler"] = \ + input_event.InputEventHandler( + self.go_next_character, + cmdnames.REVIEW_NEXT_CHARACTER) + + handlers["reviewCurrentAccessibleHandler"] = \ + input_event.InputEventHandler( + self.present_object, + cmdnames.REVIEW_CURRENT_ACCESSIBLE) + + handlers["reviewAboveHandler"] = \ + input_event.InputEventHandler( + self.go_above, + cmdnames.REVIEW_ABOVE) + + handlers["reviewBelowHandler"] = \ + input_event.InputEventHandler( + self.go_below, + cmdnames.REVIEW_BELOW) + + handlers["showContentsHandler"] = \ + input_event.InputEventHandler( + self.show_contents, + cmdnames.FLAT_REVIEW_SHOW_CONTENTS) + + handlers["flatReviewCopyHandler"] = \ + input_event.InputEventHandler( + self.copy_to_clipboard, + cmdnames.FLAT_REVIEW_COPY) + + handlers["flatReviewAppendHandler"] = \ + input_event.InputEventHandler( + self.append_to_clipboard, + cmdnames.FLAT_REVIEW_APPEND) + + handlers["flatReviewSayAllHandler"] = \ + input_event.InputEventHandler( + self.say_all, + cmdnames.SAY_ALL_FLAT_REVIEW) + + handlers["flatReviewToggleRestrictHandler"] = \ + input_event.InputEventHandler( + self.toggle_restrict, + cmdnames.TOGGLE_RESTRICT_FLAT_REVIEW) + + return handlers + + def _setup_desktop_bindings(self): + """Sets up and returns the flat-review-presenter desktop key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "KP_Subtract", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("toggleFlatReviewModeHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Add", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewSayAllHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "KP_Home", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewHomeHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Home", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewPreviousLineHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Up", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewCurrentLineHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "KP_Up", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewSpellCurrentLineHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "KP_Up", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewPhoneticCurrentLineHandler"), + 3)) + + bindings.add( + keybindings.KeyBinding( + "KP_Page_Up", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewNextLineHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Page_Up", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewEndHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Left", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewPreviousItemHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Left", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewAboveHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Begin", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewCurrentItemHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "KP_Begin", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewSpellCurrentItemHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "KP_Begin", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewPhoneticCurrentItemHandler"), + 3)) + + bindings.add( + keybindings.KeyBinding( + "KP_Begin", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewCurrentAccessibleHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Right", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewNextItemHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Right", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewBelowHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_End", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewPreviousCharacterHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_End", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewEndOfLineHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Down", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewCurrentCharacterHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "KP_Down", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewSpellCurrentCharacterHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "KP_Down", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewUnicodeCurrentCharacterHandler"), + 3)) + + bindings.add( + keybindings.KeyBinding( + "KP_Page_Down", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("reviewNextCharacterHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("showContentsHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewCopyHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewAppendHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewToggleRestrictHandler"))) + + return bindings + + def _setup_laptop_bindings(self): + """Sets up and returns the flat-review-presenter laptop key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "p", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("toggleFlatReviewModeHandler"))) + + bindings.add( + keybindings.KeyBinding( + "semicolon", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("flatReviewSayAllHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "u", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewPreviousLineHandler"))) + + bindings.add( + keybindings.KeyBinding( + "u", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("reviewHomeHandler"))) + + bindings.add( + keybindings.KeyBinding( + "i", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewCurrentLineHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "i", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewSpellCurrentLineHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "i", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewPhoneticCurrentLineHandler"), + 3)) + + bindings.add( + keybindings.KeyBinding( + "o", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewNextLineHandler"))) + + bindings.add( + keybindings.KeyBinding( + "o", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("reviewEndHandler"))) + + bindings.add( + keybindings.KeyBinding( + "j", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewPreviousItemHandler"))) + + bindings.add( + keybindings.KeyBinding( + "j", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("reviewAboveHandler"))) + + bindings.add( + keybindings.KeyBinding( + "k", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewCurrentItemHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "k", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewSpellCurrentItemHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "k", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewPhoneticCurrentItemHandler"), + 3)) + + bindings.add( + keybindings.KeyBinding( + "k", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("reviewCurrentAccessibleHandler"))) + + bindings.add( + keybindings.KeyBinding( + "l", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewNextItemHandler"))) + + bindings.add( + keybindings.KeyBinding( + "l", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("reviewBelowHandler"))) + + bindings.add( + keybindings.KeyBinding( + "m", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewPreviousCharacterHandler"))) + + bindings.add( + keybindings.KeyBinding( + "m", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("reviewEndOfLineHandler"))) + + bindings.add( + keybindings.KeyBinding( + "comma", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewCurrentCharacterHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "comma", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewSpellCurrentCharacterHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "comma", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewUnicodeCurrentCharacterHandler"), + 3)) + + bindings.add( + keybindings.KeyBinding( + "period", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("reviewNextCharacterHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("showContentsHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewCopyHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewAppendHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("flatReviewToggleRestrictHandler"))) + + return bindings + + def start(self, script=None, event=None): + """Starts flat review.""" + + if self._context: + msg = "FLAT REVIEW PRESENTER: Already in flat review" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "FLAT REVIEW PRESENTER: Starting flat review" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if script is None: + script = cthulhu_state.activeScript + + self.get_or_create_context(script) + if event is None: + return + + if _settingsManager.getSetting('speechVerbosityLevel') != settings.VERBOSITY_LEVEL_BRIEF: + script.presentMessage(messages.FLAT_REVIEW_START) + self._item_presentation(script, event, script.targetCursorCell) + + def quit(self, script=None, event=None): + """Quits flat review.""" + + if self._context is None: + msg = "FLAT REVIEW PRESENTER: Not in flat review" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "FLAT REVIEW PRESENTER: Quitting flat review" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self._context = None + cthulhu.emitRegionChanged(cthulhu_state.locusOfFocus, mode=cthulhu.FOCUS_TRACKING) + + if event is None or script is None: + return + + if _settingsManager.getSetting('speechVerbosityLevel') != settings.VERBOSITY_LEVEL_BRIEF: + script.presentMessage(messages.FLAT_REVIEW_STOP) + script.updateBraille(cthulhu_state.locusOfFocus) + + def toggle_flat_review_mode(self, script, event=None): + """Toggles between flat review mode and focus tracking mode.""" + + if self.is_active(): + self.quit(script, event) + return True + + self.start(script, event) + return True + + def go_home(self, script, event=None): + """Moves to the top left of the current window.""" + + self._context = self.get_or_create_context(script) + self._context.goBegin(flat_review.Context.WINDOW) + self.present_line(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def go_end(self, script, event=None): + """Moves to the bottom right of the current window.""" + + self._context = self.get_or_create_context(script) + self._context.goEnd(flat_review.Context.WINDOW) + self.present_line(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def go_bottom_left(self, script, event=None): + """Moves to the bottom left of the current window.""" + + self._context = self.get_or_create_context(script) + self._context.goEnd(flat_review.Context.WINDOW) + self._context.goBegin(flat_review.Context.LINE) + self.present_line(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def go_previous_line(self, script, event=None): + """Moves to the previous line.""" + + self._context = self.get_or_create_context(script) + if self._context.goPrevious(flat_review.Context.LINE, flat_review.Context.WRAP_LINE): + self.present_line(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def present_line(self, script, event=None): + """Presents the current line.""" + + self._line_presentation(script, event, 1) + return True + + def go_next_line(self, script, event=None): + """Moves to the next line.""" + + self._context = self.get_or_create_context(script) + if self._context.goNext(flat_review.Context.LINE, flat_review.Context.WRAP_LINE): + self.present_line(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def spell_line(self, script, event=None): + """Presents the current line letter by letter.""" + + self._line_presentation(script, event, 2) + return True + + def phonetic_line(self, script, event=None): + """Presents the current line letter by letter phonetically.""" + + self._line_presentation(script, event, 3) + return True + + def go_start_of_line(self, script, event=None): + """Moves to the beginning of the current line.""" + + self._context = self.get_or_create_context(script) + self._context.goEnd(flat_review.Context.LINE) + self.present_character(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def go_end_of_line(self, script, event=None): + """Moves to the end of the line.""" + + self._context = self.get_or_create_context(script) + self._context.goEnd(flat_review.Context.LINE) + self.present_character(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def go_previous_item(self, script, event=None): + """Moves to the previous item or word.""" + + self._context = self.get_or_create_context(script) + if self._context.goPrevious(flat_review.Context.WORD, flat_review.Context.WRAP_LINE): + self.present_item(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def present_item(self, script, event=None, target_cursor_cell=0): + """Presents the current item/word.""" + + self._item_presentation(script, event, target_cursor_cell, 1) + return True + + def go_next_item(self, script, event=None): + """Moves to the next item or word.""" + + self._context = self.get_or_create_context(script) + if self._context.goNext(flat_review.Context.WORD, flat_review.Context.WRAP_LINE): + self.present_item(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + + return True + + def spell_item(self, script, event=None): + """Presents the current item/word letter by letter.""" + + self._item_presentation(script, event, script.targetCursorCell, 2) + return True + + def phonetic_item(self, script, event=None): + """Presents the current word letter by letter phonetically.""" + + self._item_presentation(script, event, script.targetCursorCell, 3) + return True + + def go_previous_character(self, script, event=None): + """Moves to the previous character.""" + + self._context = self.get_or_create_context(script) + if self._context.goPrevious(flat_review.Context.CHAR, flat_review.Context.WRAP_LINE): + self.present_character(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def present_character(self, script, event=None): + """Presents the current character.""" + + self._character_presentation(script, event, 1) + return True + + def go_next_character(self, script, event=None): + """Moves to the next character.""" + + self._context = self.get_or_create_context(script) + if self._context.goNext(flat_review.Context.CHAR, flat_review.Context.WRAP_LINE): + self.present_character(script, event) + script.targetCursorCell = script.getBrailleCursorCell() + return True + + def spell_character(self, script, event=None): + """Presents the current character phonetically.""" + + self._character_presentation(script, event, 2) + return True + + def unicode_current_character(self, script, event=None): + """Presents the current character's unicode value.""" + + self._character_presentation(script, event, 3) + return True + + def go_above(self, script, event=None): + """Moves to the character above.""" + + self._context = self.get_or_create_context(script) + if self._context.goAbove(flat_review.Context.CHAR, flat_review.Context.WRAP_LINE): + self.present_item(script, event, script.targetCursorCell) + return True + + def go_below(self, script, event=None): + """Moves to the character below.""" + + self._context = self.get_or_create_context(script) + if self._context.goBelow(flat_review.Context.CHAR, flat_review.Context.WRAP_LINE): + self.present_item(script, event, script.targetCursorCell) + return True + + def get_current_object(self, script, event=None): + """Returns the current accessible object.""" + + self._context = self.get_or_create_context(script) + return self._context.getCurrentAccessible() + + def present_object(self, script, event=None): + """Presents the current accessible object.""" + + self._context = self.get_or_create_context(script) + if not isinstance(event, input_event.BrailleEvent): + script.presentObject(self._context.getCurrentAccessible(), speechonly=True) + + cthulhu.emitRegionChanged(self._context.getCurrentAccessible(), mode=cthulhu.FLAT_REVIEW) + return True + + def left_click_on_object(self, script, event=None): + """Attempts to synthesize a left click on the current accessible.""" + + self._context = self.get_or_create_context(script) + return self._context.clickCurrent(1) + + def right_click_on_object(self, script, event=None): + """Attempts to synthesize a left click on the current accessible.""" + + self._context = self.get_or_create_context(script) + return self._context.clickCurrent(3) + + def route_pointer_to_object(self, script, event=None): + """Routes the mouse pointer to the current accessible.""" + + self._context = self.get_or_create_context(script) + return self._context.routeToCurrent() + + def get_braille_regions(self, script, event=None): + """Returns the braille regions and region with focus being reviewed.""" + + self._context = self.get_or_create_context(script) + regions, focused_region = self._context.getCurrentBrailleRegions() + return [regions, focused_region] + + def _get_all_lines(self, script, event=None): + """Returns a list of textual lines representing the contents.""" + + lines = [] + self._context = self.get_or_create_context(script) + self._context.goBegin(flat_review.Context.WINDOW) + string = self._context.getCurrent(flat_review.Context.LINE)[0] + while string is not None: + lines.append(string.rstrip("\n")) + if not self._context.goNext(flat_review.Context.LINE, flat_review.Context.WRAP_LINE): + break + string = self._context.getCurrent(flat_review.Context.LINE)[0] + return lines + + def say_all(self, script, event=None): + """Speaks the contents of the entire window.""" + + for string in self._get_all_lines(script, event): + if not string.isspace(): + script.speakMessage(string, script.speechGenerator.voice(string=string)) + + return True + + def show_contents(self, script, event=None): + """Displays the entire flat review contents in a text view.""" + + msg = "FLAT REVIEW PRESENTER: Showing contents." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + text = "\n".join(self._get_all_lines(script, event)) + title = guilabels.FLAT_REVIEW_CONTENTS + self._gui = FlatReviewContextGUI(script, title, text) + self._gui.show_gui() + return True + + def copy_to_clipboard(self, script, event=None): + """Copies the string just presented to the clipboard.""" + + if not self.is_active(): + script.presentMessage(messages.FLAT_REVIEW_NOT_IN) + return True + + script.utilities.setClipboardText(self._current_contents.rstrip("\n")) + script.presentMessage(messages.FLAT_REVIEW_COPIED) + return True + + def append_to_clipboard(self, script, event=None): + """Appends the string just presented to the clipboard.""" + + if not self.is_active(): + script.presentMessage(messages.FLAT_REVIEW_NOT_IN) + return True + + script.utilities.appendTextToClipboard(self._current_contents.rstrip("\n")) + script.presentMessage(messages.FLAT_REVIEW_APPENDED) + return True + + def toggle_restrict(self, script, event=None): + """ Toggles the restricting of flat review to the current object. """ + + self._restrict = not self._restrict + _settingsManager.setSetting("flatReviewIsRestricted", self._restrict) + + if self._restrict: + script.presentMessage(messages.FLAT_REVIEW_RESTRICTED) + else: + script.presentMessage(messages.FLAT_REVIEW_UNRESTRICTED) + if self.is_active(): + # Reset the context + self._context = None + self.start() + + return True + + def _line_presentation(self, script, event, speech_type=1): + """Presents the current line.""" + + self._context = self.get_or_create_context(script) + line_string = self._context.getCurrent(flat_review.Context.LINE)[0] or "" + voice = script.speechGenerator.voice(string=line_string) + + if not isinstance(event, input_event.BrailleEvent): + if not line_string or line_string == "\n": + script.speakMessage(messages.BLANK) + elif line_string.isspace(): + script.speakMessage(messages.WHITE_SPACE) + elif line_string.isupper() and (speech_type < 2 or speech_type > 3): + script.speakMessage(line_string, voice) + elif speech_type == 2: + script.spellCurrentItem(line_string) + elif speech_type == 3: + script.phoneticSpellCurrentItem(line_string) + else: + line_string = script.utilities.adjustForRepeats(line_string) + script.speakMessage(line_string, voice) + + cthulhu.emitRegionChanged(self._context.getCurrentAccessible(), mode=cthulhu.FLAT_REVIEW) + script.updateBrailleReview() + self._current_contents = line_string + return True + + def _item_presentation(self, script, event, target_cursor_cell=0, speech_type=1): + """Presents the current item/word.""" + + self._context = self.get_or_create_context(script) + word_string = self._context.getCurrent(flat_review.Context.WORD)[0] or "" + voice = script.speechGenerator.voice(string=word_string) + if not isinstance(event, input_event.BrailleEvent): + if not word_string or word_string == "\n": + script.speakMessage(messages.BLANK) + else: + line_string = self._context.getCurrent(flat_review.Context.LINE)[0] or "" + if line_string == "\n": + script.speakMessage(messages.BLANK) + elif word_string.isspace(): + script.speakMessage(messages.WHITE_SPACE) + elif word_string.isupper() and speech_type == 1: + script.speakMessage(word_string, voice) + elif speech_type == 2: + script.spellCurrentItem(word_string) + elif speech_type == 3: + script.phoneticSpellCurrentItem(word_string) + elif speech_type == 1: + word_string = script.utilities.adjustForRepeats(word_string) + script.speakMessage(word_string, voice) + + cthulhu.emitRegionChanged(self._context.getCurrentAccessible(), mode=cthulhu.FLAT_REVIEW) + script.updateBrailleReview(target_cursor_cell) + self._current_contents = word_string + return True + + def _character_presentation(self, script, event, speech_type=1): + """Presents the current character.""" + + self._context = self.get_or_create_context(script) + char_string = self._context.getCurrent(flat_review.Context.CHAR)[0] or "" + if not isinstance(event, input_event.BrailleEvent): + if not char_string: + script.speakMessage(messages.BLANK) + else: + line_string = self._context.getCurrent(flat_review.Context.LINE)[0] or "" + if line_string == "\n" and speech_type != 3: + script.speakMessage(messages.BLANK) + elif speech_type == 3: + script.speakUnicodeCharacter(char_string) + elif speech_type == 2: + script.phoneticSpellCurrentItem(char_string) + else: + script.speakCharacter(char_string) + + cthulhu.emitRegionChanged(self._context.getCurrentAccessible(), mode=cthulhu.FLAT_REVIEW) + script.updateBrailleReview() + self._current_contents = char_string + return True + +class FlatReviewContextGUI: + """Presents the entire flat review context in a text view""" + + def __init__(self, script, title, text): + self._script = script + self._gui = self._create_dialog(title, text) + + def _create_dialog(self, title, text): + """Creates the dialog.""" + + dialog = Gtk.Dialog(title, + None, + Gtk.DialogFlags.MODAL, + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) + dialog.set_default_size(800, 600) + + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + + textbuffer = Gtk.TextBuffer() + textbuffer.set_text(text) + textbuffer.place_cursor(textbuffer.get_start_iter()) + textview = Gtk.TextView(buffer=textbuffer) + textview.set_wrap_mode(Gtk.WrapMode.WORD) + + scrolled_window.add(textview) + scrolled_window.set_hexpand(True) + scrolled_window.set_vexpand(True) + + dialog.get_content_area().pack_start(scrolled_window, True, True, 0) + dialog.connect("response", self.on_response) + + return dialog + + def on_response(self, dialog, response): + """Handler for the 'response' signal of the dialog.""" + + if response == Gtk.ResponseType.CLOSE: + self._gui.destroy() + + def show_gui(self): + """Shows the dialog.""" + + self._gui.show_all() + time_stamp = cthulhu_state.lastInputEvent.timestamp + if time_stamp == 0: + time_stamp = Gtk.get_current_event_time() + self._gui.present_with_time(time_stamp) + + +_presenter = None +def getPresenter(): + """Returns the Flat Review Presenter""" + + global _presenter + if _presenter is None: + _presenter = FlatReviewPresenter() + return _presenter diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/formatting.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/formatting.py new file mode 100644 index 0000000..ff0fdf6 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/formatting.py @@ -0,0 +1,1119 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Manages the formatting settings for Cthulhu.""" + +__id__ = "$Id:$" +__version__ = "$Revision:$" +__date__ = "$Date:$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +# If we were to adhere to the line-length requirements of 100 characters, +# this file would be even more cumbersome to look at than it already is. +# We shall respect the line-length requirements for all files that are not +# formatting.py. +# ruff: noqa: E501 + +import copy + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import object_properties + +TUTORIAL = '(tutorial and (pause + tutorial) or [])' +MNEMONIC = '(mnemonic and (pause + mnemonic + lineBreak) or [])' + +BRAILLE_TEXT = '[Text(obj, asString(labelOrName or placeholderText), asString(eol), startOffset, endOffset)]\ + + (invalid and [Region(" " + asString(invalid))])\ + + (required and [Region(" " + asString(required))])\ + + (readOnly and [Region(" " + asString(readOnly))])' + +formatting = { + + #################################################################### + # # + # Strings Cthulhu includes on its own (versus getting them from the # + # application. # + # # + #################################################################### + + 'strings' : { + 'speech': { + 'invalid': object_properties.INVALID_INDICATORS_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, + 'switch': object_properties.SWITCH_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, + 'groupindextotalunknown':object_properties.GROUP_INDEX_TOTAL_UNKNOWN_SPEECH, + 'clickable': object_properties.STATE_CLICKABLE, + 'haslongdesc': object_properties.STATE_HAS_LONGDESC, + 'hasdetails': object_properties.RELATION_HAS_DETAILS, + 'detailsfor': object_properties.RELATION_DETAILS_FOR + }, + '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, + 'invalid': object_properties.INVALID_INDICATORS_BRAILLE, + 'checkbox': object_properties.CHECK_BOX_INDICATORS_BRAILLE, + 'radiobutton': object_properties.RADIO_BUTTON_INDICATORS_BRAILLE, + 'switch': object_properties.SWITCH_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, + }, + 'sound': { + 'invalid': object_properties.INVALID_INDICATORS_SOUND, + 'required': object_properties.STATE_REQUIRED_SOUND, + 'readonly': object_properties.STATE_READ_ONLY_SOUND, + 'insensitive': object_properties.STATE_INSENSITIVE_SOUND, + 'checkbox': object_properties.CHECK_BOX_INDICATORS_SOUND, + 'radiobutton': object_properties.RADIO_BUTTON_INDICATORS_SOUND, + 'switch': object_properties.SWITCH_INDICATORS_SOUND, + 'togglebutton': object_properties.TOGGLE_BUTTON_INDICATORS_SOUND, + 'expansion': object_properties.EXPANSION_INDICATORS_SOUND, + 'multiselect': object_properties.STATE_MULTISELECT_SOUND, + 'clickable': object_properties.STATE_CLICKABLE_SOUND, + 'haslongdesc': object_properties.STATE_HAS_LONGDESC_SOUND, + 'visited': object_properties.STATE_VISITED_SOUND, + }, + }, + + #################################################################### + # # + # Formatting for speech. # + # # + #################################################################### + + 'speech': { + 'prefix': { + 'ancestor': '[]', + 'focused': 'detailsFor', + 'unfocused': 'oldAncestors + newAncestors', + 'basicWhereAmI': 'toolbar', + 'detailedWhereAmI' : '[]' + }, + 'suffix': { + 'ancestor': '[]', + 'focused': '[]', + 'unfocused': 'newNodeLevel + unselectedCell + clickable + pause + hasLongDesc + hasDetails + detailsFor +' + TUTORIAL + ' + description + pause + hasPopup', + 'basicWhereAmI': TUTORIAL + ' + clickable + hasLongDesc + description + pause + hasPopup + pause + detailsFor + pause + allDetails', + 'detailedWhereAmI': TUTORIAL + ' + clickable + hasLongDesc + description + pause + hasPopup + detailsFor + pause + allDetails' + }, + 'default': { + 'ancestor': '[]', + 'focused': '[]', + 'unfocused': 'labelOrName + roleName + availability + ' + MNEMONIC + ' + accelerator + childWidget', + 'basicWhereAmI': 'labelOrName + roleName', + 'detailedWhereAmI' : 'pageSummary' + }, + Atspi.Role.ALERT: { + 'unfocused': 'roleName + labelOrName + pause + alertText' + }, + Atspi.Role.ANIMATION: { + 'unfocused': 'labelAndName' + }, + Atspi.Role.ARTICLE: { + 'focused': 'labelOrName + roleName', + 'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection', + }, + 'ROLE_ARTICLE_IN_FEED' : { + 'unfocused': '(labelOrName or currentLineText or roleName) + pause + positionInList', + }, + Atspi.Role.BLOCK_QUOTE: { + 'focused' : 'leaving or (roleName + pause + nestingLevel)', + 'unfocused': 'roleName + pause + nestingLevel + pause + displayedText', + }, + Atspi.Role.CANVAS: { + 'focused': 'labelAndName + (imageDescription or roleName) + pause + positionInList', + 'unfocused': 'labelAndName + (imageDescription or roleName) + pause + positionInList', + 'basicWhereAmI': 'parentRoleName + pause + labelAndName + pause + selectedItemCount + pause', + 'detailedWhereAmI': 'parentRoleName + pause + labelAndName + pause + selectedItemCount + pause + selectedItems + pause' + }, + Atspi.Role.CAPTION: { + 'unfocused': '((substring and currentLineText) or labelAndName) + roleName' + }, + Atspi.Role.CHECK_BOX: { + 'focused': 'checkedState', + 'unfocused': 'labelOrName + readOnly + roleName + checkedState + required + pause + invalid + availability + ' + MNEMONIC + ' + accelerator', + 'basicWhereAmI': 'namedContainingPanel + labelOrName + readOnly + roleName + checkedState + ' + MNEMONIC + ' + accelerator + required + pause + invalid' + }, + Atspi.Role.CHECK_MENU_ITEM: { + 'focused': 'checkedState', + 'unfocused': 'labelOrName + roleName + checkedState + required + availability + ' + MNEMONIC + ' + accelerator + pause + positionInList', + 'basicWhereAmI': 'ancestors + pause + labelOrName + roleName + checkedState + pause + accelerator + pause + positionInList + ' + MNEMONIC + }, + Atspi.Role.COLOR_CHOOSER: { + 'focused': 'value', + 'unfocused': 'label + roleName + value + required + availability + ' + MNEMONIC, + 'basicWhereAmI': 'label + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required' + }, + Atspi.Role.COLUMN_HEADER: { + 'focused': 'labelAndName + roleName + pause + sortOrder + pause + newRow + pause + newColumn', + 'unfocused': '((substring and currentLineText) or labelAndName) + roleName + pause + sortOrder + pause + newRow + pause + newColumn' + }, + Atspi.Role.COMBO_BOX: { + 'focused': 'labelOrName + roleName + expandableState', + 'unfocused': 'labelOrName + roleName + pause + value + pause + positionInList + ' + MNEMONIC + ' + accelerator', + }, + Atspi.Role.COMMENT: { + 'focused': 'labelOrName + roleName', + 'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection', + }, + # TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one. + 'ROLE_CONTENT_DELETION': { + 'focused': 'leaving or deletionStart', + 'unfocused': 'deletionStart + pause + displayedText + pause + deletionEnd', + }, + 'ROLE_CONTENT_ERROR': { + 'unfocused': 'displayedText + pause + invalid', + }, + # TODO - JD: When we bump dependencies to 2.34, remove this fake role and use the real one. + 'ROLE_CONTENT_INSERTION': { + 'focused': 'leaving or insertionStart', + 'unfocused': 'insertionStart + pause + displayedText + pause + insertionEnd', + }, + # TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one. + 'ROLE_CONTENT_MARK': { + 'focused': 'leaving or markStart', + 'unfocused': 'markStart + pause + displayedText + pause + markEnd', + }, + # TODO - JD: When we bump dependencies to 2.36, remove this fake role and use the real one. + 'ROLE_CONTENT_SUGGESTION': { + 'focused': 'leaving or roleName', + }, + Atspi.Role.DESCRIPTION_LIST: { + 'focused' : 'leaving or (labelOrName + pause + (numberOfChildren or roleName) + pause + nestingLevel)', + 'unfocused': 'labelOrName + pause + focusedItem + pause + multiselectableState + (numberOfChildren or roleName) + pause' + }, + Atspi.Role.DESCRIPTION_TERM: { + 'unfocused': '(labelOrName or (displayedText + allTextSelection)) + roleName + pause + termValueCount + pause + positionInList', + }, + Atspi.Role.DESCRIPTION_VALUE: { + 'unfocused': '(labelOrName or (displayedText + allTextSelection)) + roleName + pause + positionInList', + }, + Atspi.Role.DIAL: { + 'focused': 'value', + 'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required' + }, + Atspi.Role.DIALOG: { + 'focused': 'labelOrName + roleName + (unrelatedLabelsOrDescription)', + 'unfocused': '(expandedEOCs or (labelOrName + roleName + (unrelatedLabelsOrDescription)))' + }, + Atspi.Role.DOCUMENT_FRAME: { + 'unfocused': 'labelOrName + readOnly + textRole + currentLineText + anyTextSelection + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC, + 'detailedWhereAmI': 'labelOrName + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + }, + Atspi.Role.DOCUMENT_WEB: { + 'unfocused': 'labelOrName + readOnly + textRole + currentLineText + anyTextSelection + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC, + 'detailedWhereAmI': 'labelorName + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + }, + 'ROLE_DPUB_LANDMARK': { + 'focused': 'leaving or labelOrName', + 'unfocused': 'labelOrName + currentLineText + allTextSelection' + }, + 'ROLE_DPUB_SECTION': { + 'focused': 'leaving or (labelOrName + roleName)', + 'unfocused': 'labelOrName + currentLineText + allTextSelection' + }, + Atspi.Role.EMBEDDED: { + 'focused': 'labelOrName + roleName + availability', + 'unfocused': '(expandedEOCs or (labelOrName + unrelatedLabels)) + roleName + availability' + }, + Atspi.Role.ENTRY: { + 'focused': 'labelOrName + readOnly + textRole + (currentLineText or placeholderText) + allTextSelection', + 'unfocused': 'labelOrName + readOnly + textRole + (currentLineText or placeholderText) + allTextSelection + required + pause + invalid + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + readOnly + textRole + (textContent or placeholderText) + anyTextSelection + required + pause + invalid + ' + MNEMONIC, + 'detailedWhereAmI': 'labelOrName + readOnly + textRole + (textContentWithAttributes or placeholderText) + anyTextSelection + required + pause + invalid + ' + MNEMONIC, + }, + 'ROLE_FEED': { + 'focused': 'leaving or (labelOrName + pause + (numberOfChildren or roleName))', + 'unfocused': 'labelOrName + pause + (numberOfChildren or roleName)', + }, + Atspi.Role.FOOTNOTE: { + 'unfocused': 'labelOrName + roleName + pause + currentLineText + allTextSelection', + }, + Atspi.Role.FOOTER: { + 'unfocused': '(displayedText or name) + roleName', + }, + Atspi.Role.FORM: { + 'focused': 'leaving or (labelAndName + roleName)', + 'unfocused': '((substring and currentLineText) or labelAndName) + roleName' + }, + Atspi.Role.FRAME: { + 'focused': 'labelOrName', + 'unfocused': 'labelOrName + roleName + unfocusedDialogCount + availability' + }, + Atspi.Role.HEADER: { + 'unfocused': '(displayedText or name) + roleName', + }, + Atspi.Role.HEADING: { + 'focused': 'displayedText + roleName + expandableState', + 'unfocused': 'displayedText + roleName + expandableState', + 'basicWhereAmI': 'label + readOnly + textRole + pause + textContent + anyTextSelection + ' + MNEMONIC, + 'detailedWhereAmI': 'label + readOnly + textRole + pause + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + }, + Atspi.Role.ICON: { + 'focused': 'labelAndName + (imageDescription or roleName) + pause + positionInList', + 'unfocused': 'labelAndName + (imageDescription or roleName) + pause + positionInList', + 'basicWhereAmI': 'parentRoleName + pause + labelAndName + pause + selectedItemCount + pause', + 'detailedWhereAmI': 'parentRoleName + pause + labelAndName + pause + selectedItemCount + pause + selectedItems + pause' + }, + Atspi.Role.IMAGE: { + 'unfocused': 'labelAndName + roleName' + }, + Atspi.Role.INFO_BAR: { + 'unfocused': 'labelAndName + unrelatedLabels' + }, + Atspi.Role.INTERNAL_FRAME: { + 'unfocused': 'labelAndName + roleName' + }, + Atspi.Role.LABEL: { + 'unfocused': 'label + ((displayedText + allTextSelection) or name) + roleName', + }, + Atspi.Role.LANDMARK: { + 'focused': 'leaving or (roleName + labelAndName)', + 'unfocused': 'roleName + (labelAndName or (substring and currentLineText)) + pause + unrelatedLabels' + }, + Atspi.Role.LAYERED_PANE: { + 'focused': '(labelAndName or roleName) + availability + noShowingChildren', + 'unfocused': '(labelAndName or roleName) + availability + noShowingChildren', + 'basicWhereAmI': '(labelAndName or roleName) + pause + selectedItemCount + pause', + 'detailedWhereAmI': '(labelAndName or roleName) + pause + roleName + pause + selectedItemCount + pause + selectedItems + pause' + }, + Atspi.Role.LINK: { + 'unfocused': '(name or displayedText) + roleName + pause + expandableState + availability + ' + MNEMONIC, + 'basicWhereAmI': 'linkInfo + pause + siteDescription + pause + fileSize + pause + ' + MNEMONIC + }, + Atspi.Role.LIST: { + 'focused' : 'leaving or (labelOrName + pause + (numberOfChildren or roleName) + pause + nestingLevel)', + 'unfocused': 'labelOrName + pause + focusedItem + pause + multiselectableState + (numberOfChildren or roleName) + pause' + }, + Atspi.Role.LIST_BOX: { + 'focused': 'labelOrName + multiselectableState + (numberOfChildren or roleName)', + 'unfocused': 'labelOrName + pause + focusedItem + pause + multiselectableState + (numberOfChildren or roleName) + pause' + }, + Atspi.Role.LIST_ITEM: { + 'focused': 'checkedStateIfCheckable + pause + expandableState', + 'unfocused': '(labelOrName or (displayedText + allTextSelection)) + checkedStateIfCheckable + pause + unselectedStateIfSelectable + pause + expandableState + pause + positionInList + pause + listBoxItemWidgets', + 'basicWhereAmI': 'label + roleName + pause + (name or displayedText) + checkedStateIfCheckable + pause + unselectedStateIfSelectable + pause + positionInList + pause + expandableState + (nodeLevel or nestingLevel) + pause' + }, + Atspi.Role.MATH: { + 'unfocused': 'math', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_ENCLOSED': { + 'unfocused': 'enclosedBase + enclosedEnclosures', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_FENCED': { + 'unfocused': 'fencedStart + pause + fencedContents + pause + fencedEnd', + }, + Atspi.Role.MATH_FRACTION: { + 'unfocused': 'fractionStart + pause + fractionNumerator + fractionLine + fractionDenominator + pause + fractionEnd + pause', + }, + Atspi.Role.MATH_ROOT: { + 'unfocused': 'rootStart + rootBase + pause + rootEnd + pause', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_MULTISCRIPT': { + 'unfocused': 'scriptBase + pause + scriptPrescripts + pause + scriptPostscripts + pause', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_SCRIPT_SUBSUPER': { + 'unfocused': 'scriptBase + pause + scriptSubscript + pause + scriptSuperscript + pause', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_SCRIPT_UNDEROVER': { + 'unfocused': 'scriptBase + pause + scriptUnderscript + pause + scriptOverscript + pause', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_TABLE': { + 'unfocused': 'mathTableStart + pause + mathTableRows + pause + mathTableEnd + pause', + }, + # TODO - JD: When we bump dependencies to TBD, remove this fake role and use the real one. + 'ROLE_MATH_TABLE_ROW': { + 'unfocused': 'mathRow', + }, + Atspi.Role.MENU: { + 'focused': 'labelOrName + roleName', + 'unfocused': 'labelOrName + roleName + availability + ' + MNEMONIC + ' + accelerator + pause + positionInList', + 'basicWhereAmI': '(ancestors or parentRoleName) + pause + labelOrName + roleName + pause + positionInList + ' + MNEMONIC + }, + Atspi.Role.MENU_ITEM: { + 'focused': 'expandableState', + 'unfocused': 'labelOrName + checkedStateIfCheckable + expandableState + availability + ' + MNEMONIC + ' + accelerator + pause + positionInList', + 'basicWhereAmI': 'ancestors + pause + labelOrName + checkedStateIfCheckable + pause + accelerator + pause + positionInList + ' + MNEMONIC + }, + Atspi.Role.NOTIFICATION: { + 'unfocused': 'roleName + labelOrName + pause + (expandedEOCs or unrelatedLabelsOrDescription)' + }, + Atspi.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 + }, + Atspi.Role.PAGE_TAB: { + 'focused': 'labelOrName + roleName + availability + pause + positionInList + ' + MNEMONIC + ' + accelerator', + 'unfocused': 'labelOrName + roleName + availability + pause + positionInList + ' + MNEMONIC + ' + accelerator', + 'basicWhereAmI': 'parentRoleName + pause + labelOrName + roleName + availability + pause + positionInList + ' + MNEMONIC + ' + accelerator' + }, + Atspi.Role.PANEL: { + 'focused': 'leaving or (labelAndName + roleName + availability + pause + unrelatedLabels)', + 'unfocused': '((substring and currentLineText) or labelAndName) + roleName + availability + pause + unrelatedLabels' + }, + Atspi.Role.PARAGRAPH: { + 'focused': 'labelOrName + readOnly + textRole + textIndentation + currentLineText + allTextSelection', + 'unfocused': 'labelOrName + readOnly + textRole + textIndentation + currentLineText + allTextSelection + ' + MNEMONIC, + 'basicWhereAmI': 'label + readOnly + textRole + textContent + anyTextSelection + ' + MNEMONIC, + 'detailedWhereAmI': 'label + readOnly + textRole + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + }, + Atspi.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 + }, + Atspi.Role.PROGRESS_BAR: { + 'focused': 'progressBarIndex + (progressBarValue or roleName)', + 'unfocused': 'progressBarIndex + labelAndName + (progressBarValue or roleName)' + }, + Atspi.Role.PUSH_BUTTON: { + 'focused': 'expandableState', + 'unfocused': 'labelAndName + expandableState + roleName + availability + ' + MNEMONIC + ' + accelerator', + 'basicWhereAmI': 'labelAndName + expandableState + roleName + ' + MNEMONIC + ' + accelerator' + }, + Atspi.Role.RADIO_BUTTON: { + 'focused': 'radioState', + 'unfocused': 'newRadioButtonGroup + pause + (name or label) + pause + radioState + roleName + availability + lineBreak + ' + MNEMONIC + ' + accelerator + pause + positionInList + pause', + 'basicWhereAmI': 'radioButtonGroup + pause + (name or label) + roleName + pause + radioState + pause + positionInGroup + ' + MNEMONIC + ' + accelerator' + }, + Atspi.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 Cthulhu bug #433398 for more details. + # + 'focused': 'labelOrName + radioState + roleName + availability + positionInList', + 'unfocused': 'labelOrName + radioState + roleName + availability + ' + MNEMONIC + ' + accelerator + positionInList', + 'basicWhereAmI': 'ancestors + labelOrName + roleName + radioState + accelerator + positionInList + ' + MNEMONIC + }, + 'ROLE_REGION': { + 'focused': 'leaving or (roleName + labelOrName)', + 'unfocused': 'labelOrName + roleName + currentLineText + allTextSelection' + }, + Atspi.Role.ROW_HEADER: { + 'focused': 'labelAndName + roleName + pause + sortOrder + pause + newRow + pause + newColumn', + 'unfocused': '((substring and currentLineText) or labelAndName) + roleName + pause + sortOrder + pause + newRow + pause + newColumn' + }, + Atspi.Role.SCROLL_BAR: { + 'focused': 'value', + 'unfocused': 'labelOrName + roleName + value + required + availability + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required' + }, + Atspi.Role.SCROLL_PANE: { + 'unfocused': '(currentLineText + allTextSelection) or (labelOrName + roleName)', + }, + Atspi.Role.SECTION: { + 'focused': '(labelOrName or (currentLineText + allTextSelection)) + roleName', + 'unfocused': '(labelOrName or (currentLineText + allTextSelection)) + roleName + ' + MNEMONIC, + }, + Atspi.Role.SLIDER: { + 'focused': 'value', + 'unfocused': 'labelOrName + roleName + value + required + pause + invalid + availability + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + roleName + value + percentage + ' + MNEMONIC + ' + accelerator + required + pause + invalid' + }, + Atspi.Role.SPIN_BUTTON: { + 'focused': '(displayedText or value)', + 'unfocused': 'labelAndName + (displayedText or value) + roleName + required + pause + invalid + availability + ' + MNEMONIC, + 'basicWhereAmI': 'label + roleName + name + (displayedText or value) + ' + MNEMONIC + ' + accelerator + required + pause + invalid' + }, + Atspi.Role.SEPARATOR: { + 'focused': 'roleName + availability', + 'unfocused': 'roleName + availability + (labelOrName or displayedText or value) + ' + MNEMONIC, + }, + Atspi.Role.SPLIT_PANE: { + 'focused': 'value', + 'unfocused': 'labelAndName + roleName + value + availability + ' + MNEMONIC, + 'basicWhereAmI' : 'labelAndName + roleName + value' + }, + Atspi.Role.STATIC: { + 'unfocused': '(displayedText or name) + roleName', + }, + Atspi.Role.STATUS_BAR: { + 'focused': 'labelAndName + roleName', + 'unfocused': 'labelAndName + roleName + pause + statusBar', + }, + Atspi.Role.SUBSCRIPT: { + 'unfocused': 'roleName + currentLineText + allTextSelection', + }, + Atspi.Role.SUPERSCRIPT: { + 'unfocused': 'roleName + currentLineText + allTextSelection', + }, + 'ROLE_SWITCH': { + 'focused': 'switchState', + 'unfocused': 'labelOrName + roleName + switchState + availability + ' + MNEMONIC + ' + accelerator', + 'basicWhereAmI': 'labelOrName + roleName + switchState' + }, + Atspi.Role.TABLE: { + 'focused': 'leaving or (labelAndName + pause + table)', + 'unfocused': 'labelAndName + pause + table', + 'basicWhereAmI': 'labelAndName + pause + table' + }, + Atspi.Role.TABLE_CELL: { + 'ancestor': 'newRowHeader + newColumnHeader + pause + newRow + pause + newColumn', + 'focused': '((tableCell2ChildLabel + tableCell2ChildToggle) or cellCheckedState) + pause + (expandableState and (expandableState + pause + numberOfChildren + pause))', + 'unfocused': 'tableCellRow + pause', + 'basicWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + expandableState + pause + nodeLevel + pause', + 'detailedWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + tableCellRow + pause + expandableState + pause + nodeLevel + pause', + }, + 'REAL_ROLE_TABLE_CELL': { + # the real cell information + # note that Atspi.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 + pause + invalid)' + }, + Atspi.Role.TABLE_ROW: { + 'focused': 'expandableState', + 'unfocused': '(labelOrName or displayedText) + pause + expandableState + pause + positionInList', + 'basicWhereAmI': '(labelOrName or displayedText) + roleName + pause + positionInList + pause + expandableState + (nodeLevel or nestingLevel)' + }, + Atspi.Role.TEAROFF_MENU_ITEM: { + 'focused': '[]', + 'unfocused': 'labelOrName + roleName + availability ' + }, + Atspi.Role.TERMINAL: { + 'focused': 'textContent', + 'unfocused': 'textContent', + 'basicWhereAmI': 'label + readOnly + pause + textRole + pause + textContent + anyTextSelection + ' + MNEMONIC, + 'detailedWhereAmI': 'label + readOnly + pause + textRole + pause + textContentWithAttributes + anyTextSelection + ' + MNEMONIC + }, + Atspi.Role.TEXT: { + 'focused': 'labelOrName + readOnly + textRole + pause + textIndentation + (currentLineText or placeholderText) + allTextSelection', + 'unfocused': 'labelOrName + readOnly + textRole + pause + textIndentation + (currentLineText or placeholderText) + allTextSelection + ' + MNEMONIC, + 'basicWhereAmI': 'labelOrName + readOnly + textRole + pause + (textContent or placeholderText) + anyTextSelection + pause + ' + MNEMONIC, + 'detailedWhereAmI': 'labelOrName + readOnly + textRole + pause + (textContentWithAttributes or placeholderText) + anyTextSelection + pause + ' + MNEMONIC + }, + Atspi.Role.TOGGLE_BUTTON: { + 'focused': 'expandableState or toggleState', + 'unfocused': 'labelOrName + roleName + (expandableState or toggleState) + availability + ' + MNEMONIC + ' + accelerator', + 'basicWhereAmI': 'labelOrName + roleName + (expandableState or toggleState)' + }, + Atspi.Role.TOOL_BAR: { + 'focused': 'labelAndName + roleName', + 'unfocused': 'labelAndName + roleName', + }, + Atspi.Role.TOOL_TIP: { + 'focused': 'leaving or roleName', + 'unfocused': 'roleName + labelAndName', + 'basicWhereAmI': 'roleName + labelAndName' + }, + Atspi.Role.TREE: { + 'focused': 'labelAndName + roleName', + 'unfocused': 'labelAndName + roleName', + }, + Atspi.Role.TREE_ITEM: { + 'focused': 'expandableState', + 'unfocused': '(labelOrName or displayedText) + pause + expandableState + pause + positionInList', + 'basicWhereAmI': '(labelOrName or displayedText) + roleName + pause + positionInList + pause + expandableState + (nodeLevel or nestingLevel)' + }, + }, + + #################################################################### + # # + # 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 + invalid))]', + 'unfocused': '[Component(obj,\ + asString(label + displayedText + value + roleName + required + invalid))]', + }, + Atspi.Role.ALERT: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelAndName + roleName))]))' + }, + Atspi.Role.ANIMATION: { + 'unfocused': '[Component(obj,\ + asString(label + displayedText + roleName + (description and space(": ") + description)))]', + }, + Atspi.Role.APPLICATION: { + 'focused': '[Component(obj, asString(name + roleName))]', + 'unfocused': '[Component(obj, asString(name + roleName))]', + }, + Atspi.Role.ARTICLE: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelAndName + roleName))]\ + + (childWidget and ([Region(" ")] + childWidget))))' + }, + 'ROLE_ARTICLE_IN_FEED': { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelOrName + roleName))]))' + }, + #Atspi.Role.ARROW: 'default' + Atspi.Role.BLOCK_QUOTE: { + 'unfocused': BRAILLE_TEXT + ' + (roleName and [Region(" " + asString(roleName + nestingLevel))])', + }, + Atspi.Role.CANVAS: { + 'unfocused': '[Component(obj,\ + asString(((label + displayedText + imageDescription) or name) + roleName))]' + }, + Atspi.Role.CHECK_BOX: { + 'unfocused': '[Component(obj,\ + asString(labelOrName + roleName),\ + indicator=asString(checkedState))]' + }, + Atspi.Role.CHECK_MENU_ITEM: { + 'unfocused': '[Component(obj,\ + asString(label + displayedText + roleName + availability) + asString(accelerator),\ + indicator=asString(checkedState))]' + }, + Atspi.Role.COLUMN_HEADER: { + 'unfocused': '[Component(obj,\ + asString(((substring and currentLineText) or labelAndName) + roleName + sortOrder))]', + }, + Atspi.Role.COMBO_BOX: { + 'unfocused': '[Component(obj, asString(labelOrName + value + roleName), \ + labelOrName and (len(asString(labelOrName)) + 1) or 0)]' + }, + Atspi.Role.DESCRIPTION_TERM: { + 'unfocused': BRAILLE_TEXT + ' + ([Region(" " + asString(termValueCount))])', + }, + #Atspi.Role.DESKTOP_ICON: 'default' + Atspi.Role.DIAL: { + 'unfocused': '[Component(obj,\ + asString(labelOrName + value + roleName + required))]' + }, + Atspi.Role.DIALOG: { + 'unfocused': '[Component(obj, asString(labelOrName + roleName + (unrelatedLabelsOrDescription)))]' + }, + #Atspi.Role.DIRECTORY_PANE: 'default' + Atspi.Role.DOCUMENT_FRAME: { + 'focused': '[Text(obj, asString(placeholderText), asString(eol), startOffset, endOffset)]\ + + (required and [Region(" " + asString(required))])\ + + (readOnly and [Region(" " + asString(readOnly))])', + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.DOCUMENT_WEB: { + 'focused': '[Text(obj, asString(placeholderText), asString(eol), startOffset, endOffset)]\ + + (required and [Region(" " + asString(required))])\ + + (readOnly and [Region(" " + asString(readOnly))])', + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.ENTRY: { + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.FORM: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelAndName + roleName))]))' + }, + Atspi.Role.FRAME: { + 'focused': '[Component(obj,\ + asString(labelOrName + roleName + alertAndDialogCount))]', + 'unfocused': '[Component(obj,\ + asString(labelOrName + roleName + alertAndDialogCount))]', + }, + Atspi.Role.HEADING: { + 'unfocused': '[Text(obj, asString(placeholderText), "", startOffset, endOffset)]\ + + [Region(" " + asString(roleName))]' + }, + #Atspi.Role.HTML_CONTAINER: 'default' + Atspi.Role.ICON: { + 'unfocused': '[Component(obj,\ + asString(((label + displayedText + imageDescription) or name) + roleName))]' + }, + Atspi.Role.IMAGE: { + 'focused': '[Component(obj,\ + asString(labelAndName + value + roleName + required))]', + 'unfocused': '[Component(obj,\ + asString(labelAndName + value + roleName + required))]', + }, + Atspi.Role.LABEL: { + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.LINK: { + 'unfocused': '[Link(obj, asString(name or displayedText))] \ + + (roleName and [Region(" " + asString(roleName))])', + }, + Atspi.Role.LIST: { + 'unfocused': '[Component(obj,\ + asString(label + focusedItem + roleName),\ + asString(label) and (len(asString(label)) + 1) or 0)]' + }, + Atspi.Role.LIST_BOX: { + 'unfocused': '[Component(obj,\ + asString(label + focusedItem + roleName),\ + asString(label) and (len(asString(label)) + 1) or 0)]' + }, + Atspi.Role.LIST_ITEM: { + 'focused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj,\ + asString(label + displayedText + expandableState + roleName + availability) + asString(accelerator), indicator=asString(checkedStateIfCheckable))] \ + + (nestingLevel and [Region(" " + asString(nestingLevel))])\ + + (listBoxItemWidgets and ([Region(" ")] + listBoxItemWidgets))))', + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelOrName + expandableState))]\ + + (nestingLevel and [Region(" " + asString(nestingLevel))])\ + + (listBoxItemWidgets and ([Region(" ")] + listBoxItemWidgets))))', + }, + Atspi.Role.MENU: { + 'focused': '[Component(obj,\ + asString(labelOrName + roleName + availability) + asString(accelerator))]', + 'unfocused': '[Component(obj,\ + asString(labelOrName + roleName))]', + }, + #Atspi.Role.MENU_BAR: 'default' + Atspi.Role.MENU_ITEM: { + 'unfocused': '[Component(obj,\ + asString(labelOrName + expandableState + availability) + asString(accelerator),\ + indicator=asString(checkedStateIfCheckable))]' + }, + Atspi.Role.NOTIFICATION: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelAndName + roleName))]))' + }, + Atspi.Role.PAGE: { + 'unfocused': BRAILLE_TEXT + }, + #Atspi.Role.OPTION_PANE: 'default' + Atspi.Role.PAGE_TAB: { + 'focused': '[Component(obj,\ + asString(labelOrName + roleName + availability) + asString(accelerator))]', + 'unfocused': '[Component(obj,\ + asString(labelOrName + roleName))]' + }, + #Atspi.Role.PAGE_TAB_LIST: 'default' + Atspi.Role.PANEL: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelAndName + roleName))]\ + + (childWidget and ([Region(" ")] + childWidget))))' + }, + Atspi.Role.PARAGRAPH: { + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.PASSWORD_TEXT: { + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.PROGRESS_BAR: { + 'unfocused': '(progressBarValue and \ + [Component(obj, asString(labelAndName + progressBarValue + roleName + progressBarIndex))]) \ + or []' + }, + Atspi.Role.PUSH_BUTTON: { + 'unfocused': '[Component(obj,\ + asString((labelAndName or description) + expandableState + roleName))]' + }, + Atspi.Role.RADIO_BUTTON: { + 'unfocused': '[Component(obj,\ + asString((labelOrName or description) + roleName),\ + indicator=asString(radioState))]' + }, + Atspi.Role.RADIO_MENU_ITEM: { + 'focused': '[Component(obj,\ + asString((labelOrName or description) + roleName + availability)\ + + asString(accelerator),\ + indicator=asString(radioState))]', + 'unfocused': '[Component(obj,\ + asString(labelOrName or description)\ + + asString(accelerator),\ + indicator=asString(radioState))]' + }, + Atspi.Role.ROW_HEADER: { + 'unfocused': '[Component(obj,\ + asString(((substring and currentLineText) or labelAndName) + roleName + sortOrder))]', + }, + Atspi.Role.SCROLL_BAR: { + 'unfocused': '[Component(obj,\ + asString(labelOrName + value + roleName + required))]' + }, + Atspi.Role.SCROLL_PANE: { + 'unfocused': 'asPageTabOrScrollPane' + }, + Atspi.Role.SECTION: { + 'unfocused': BRAILLE_TEXT + }, + #'REAL_ROLE_SCROLL_PANE': 'default' + Atspi.Role.SLIDER: { + 'unfocused': '[Component(obj,\ + asString(labelOrName + value + roleName + required + invalid))]' + }, + Atspi.Role.SPIN_BUTTON: { + 'unfocused': '[Text(obj, asString(label), asString(eol))]\ + + (required and [Region(" " + asString(required))] or [])\ + + (readOnly and [Region(" " + asString(readOnly))] or [])' + }, + Atspi.Role.STATUS_BAR: { + 'unfocused': '[Component(obj, asString(labelOrName + roleName))]\ + + [Region(" ")] + statusBar', + }, + 'ROLE_SWITCH' : { + 'unfocused': '[Component(obj,\ + asString((labelOrName or description) + roleName),\ + indicator=asString(switchState))]' + }, + #Atspi.Role.SPLIT_PANE: 'default' + #Atspi.Role.TABLE: 'default' + Atspi.Role.TABLE_CELL: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ') or tableCellRow)', + }, + 'REAL_ROLE_TABLE_CELL': { + 'unfocused': '((tableCell2ChildToggle + tableCell2ChildLabel)\ + or (substring and ' + BRAILLE_TEXT + ') \ + or (cellCheckedState\ + + (columnHeaderIfToggleAndNoText and [Region(" "), Component(obj, asString(columnHeaderIfToggleAndNoText))])\ + + ((realActiveDescendantDisplayedText and [Component(obj, asString(realActiveDescendantDisplayedText))])\ + or (imageDescription and [Region(" "), Component(obj, asString(imageDescription))]))\ + + (realActiveDescendantRoleName and [Component(obj, (realActiveDescendantDisplayedText and " " or "") + asString(realActiveDescendantRoleName))])\ + + (expandableState and [Region(" " + asString(expandableState))])\ + + (required and [Region(" " + asString(required))]))\ + or ([Component(obj,"")]))' + }, + #Atspi.Role.TABLE_COLUMN_HEADER: 'default' + #Atspi.Role.TABLE_ROW_HEADER: 'default' + Atspi.Role.TEAROFF_MENU_ITEM: { + 'unfocused': '[Component(obj,\ + asString(roleName))]' + }, + Atspi.Role.TERMINAL: { + 'unfocused': '[Text(obj)]' + }, + Atspi.Role.TEXT: { + 'unfocused': BRAILLE_TEXT + }, + Atspi.Role.TOGGLE_BUTTON: { + 'unfocused': '[Component(obj,\ + asString((labelOrName or description) + expandableState + roleName),\ + indicator=asString(toggleState))]' + }, + Atspi.Role.TOOL_BAR: { + 'unfocused': '[Component(obj, asString(labelOrName + roleName))]', + }, + Atspi.Role.TREE: { + 'unfocused': '[Component(obj, asString(labelOrName + roleName))]', + }, + Atspi.Role.TREE_ITEM: { + 'unfocused': '((substring and ' + BRAILLE_TEXT + ')\ + or ([Component(obj, asString(labelOrName + expandableState))]\ + + (nodeLevel and [Region(" " + asString(nodeLevel))])))', + }, + #Atspi.Role.TREE: 'default' + #Atspi.Role.TREE_TABLE: 'default' + #Atspi.Role.WINDOW: 'default' + }, + + #################################################################### + # # + # Formatting for sound. # + # # + #################################################################### + + 'sound': { + 'prefix': { + 'focused': '[]', + 'unfocused': '[]', + 'basicWhereAmI': '[]', + 'detailedWhereAmI': '[]' + }, + 'suffix': { + 'focused': '[]', + 'unfocused': 'clickable + hasLongDesc', + 'basicWhereAmI': '[]', + 'detailedWhereAmI': '[]' + }, + 'default': { + 'focused': '[]', + 'unfocused': 'roleName', + 'basicWhereAmI': '[]', + 'detailedWhereAmI': '[]' + }, + Atspi.Role.CANVAS: { + 'unfocused': 'roleName + positionInSet', + }, + Atspi.Role.CHECK_BOX: { + 'focused': 'checkedState', + 'unfocused': 'roleName + checkedState + required + invalid + availability', + }, + Atspi.Role.CHECK_MENU_ITEM: { + 'focused': 'checkedState', + 'unfocused': 'roleName + checkedState + availability + positionInSet', + }, + Atspi.Role.COMBO_BOX: { + 'focused': 'expandableState', + 'unfocused': 'roleName + positionInSet', + }, + Atspi.Role.DIAL: { + 'focused': 'percentage', + 'unfocused': 'roleName + percentage + required + invalid + availability', + }, + Atspi.Role.ENTRY: { + 'unfocused': 'roleName + readOnly + required + invalid + availability', + }, + Atspi.Role.HEADING: { + 'focused': 'expandableState', + 'unfocused': 'roleName + expandableState', + }, + Atspi.Role.ICON: { + 'unfocused': 'roleName + positionInSet', + }, + Atspi.Role.LINK: { + 'focused': 'expandableState', + 'unfocused': 'roleName + visitedState + expandableState', + }, + Atspi.Role.LIST: { + 'unfocused': 'roleName + multiselectableState', + }, + Atspi.Role.LIST_BOX: { + 'unfocused': 'roleName + multiselectableState', + }, + Atspi.Role.LIST_ITEM: { + 'focused': 'expandableState', + 'unfocused': 'roleName + expandableState + positionInSet', + }, + Atspi.Role.MENU_ITEM: { + 'focused': 'expandableState', + 'unfocused': 'roleName + expandableState + availability + positionInSet', + }, + Atspi.Role.PAGE_TAB: { + 'unfocused': 'roleName + positionInSet', + }, + Atspi.Role.PROGRESS_BAR: { + 'focused': 'progressBarValue', + 'unfocused': 'roleName + progressBarValue' + }, + Atspi.Role.PUSH_BUTTON: { + 'focused': 'expandableState', + 'unfocused': 'roleName + expandableState + availability', + }, + Atspi.Role.RADIO_BUTTON: { + 'focused': 'radioState', + 'unfocused': 'roleName + radioState + availability + positionInSet', + }, + Atspi.Role.RADIO_MENU_ITEM: { + 'focused': 'radioState', + 'unfocused': 'roleName + checkedState + availability + positionInSet', + }, + Atspi.Role.SCROLL_BAR: { + 'focused': 'percentage', + 'unfocused': 'roleName + percentage', + }, + Atspi.Role.SLIDER: { + 'focused': 'percentage', + 'unfocused': 'roleName + percentage + required + invalid + availability', + }, + Atspi.Role.SPIN_BUTTON: { + 'focused': 'percentage', + 'unfocused': 'roleName + availability + percentage + required + invalid', + }, + Atspi.Role.SPLIT_PANE: { + 'focused': 'percentage', + 'unfocused': 'roleName + percentage + availability', + }, + 'ROLE_SWITCH': { + 'focused': 'switchState', + 'unfocused': 'roleName + switchState + availability', + }, + Atspi.Role.TABLE_CELL: { + 'focused': 'expandableState', + 'unfocused': 'roleName + expandableState', + }, + Atspi.Role.TABLE_ROW: { + 'focused': 'expandableState', + }, + Atspi.Role.TEXT: { + 'unfocused': 'roleName + readOnly + required + invalid + availability', + }, + Atspi.Role.TOGGLE_BUTTON: { + 'focused': 'expandableState or toggleState', + 'unfocused': 'roleName + (expandableState or toggleState) + availability', + }, + Atspi.Role.TREE_ITEM: { + 'focused': 'expandableState', + 'unfocused': 'roleName + expandableState + positionInSet', + }, + }, +} + +class Formatting(dict): + + def __init__(self, script): + dict.__init__(self) + self._script = script + self.update(copy.deepcopy(formatting)) + + def update(self, newDict): + for key, val in newDict.items(): + if key in self: + if isinstance(self[key], dict) and isinstance(val, dict): + self[key].update(val) + elif isinstance(self[key], str) \ + and isinstance(val, str): + self[key] = val + else: + # exception or such like, we are trying to merge + # incompatible trees. + # throw an exception? + print("an error has occurred, cant merge dicts.") + else: + self[key] = val + + def getPrefix(self, **args): + """Get a formatting string to add on to the end of + formatting strings obtained by getFormat. + + Arguments expected in args: + - mode: output mode, such as 'speech', 'braille'. + - formatType: the type of formatting, such as + 'focused', 'basicWhereAmI', etc. + """ + prefix = self[args['mode']]['prefix'][args['formatType']] + return prefix + + def getSuffix(self, **args): + """Get a formatting string to add on to the end of + formatting strings obtained by getFormat. + + Arguments expected in args: + - mode: output mode, such as 'speech', 'braille'. + - role: the role, such as Atspi.Role.TEXT + - formatType: the type of formatting, such as + 'focused', 'basicWhereAmI', etc. + """ + suffix = self[args['mode']]['suffix'][args['formatType']] + return suffix + + def getString(self, **args): + """Gets a human consumable string for a specific value + (e.g., an indicator for a checkbox state). + + Arguments expected in args: + - mode: output mode, such as 'speech', 'braille'. + - stringType: the type of the string to get (see the dictionary above). + """ + return self['strings'][args['mode']][args['stringType']] + + def getFormat(self, **args): + """Get a formatting string for the given mode and formatType for a + role (e.g., a where am I string for a text object). + + Arguments expected in args: + - mode: output mode, such as 'speech', 'braille'. + - role: the role, such as Atspi.Role.TEXT + - formatType: the type of formatting, such as + 'focused', 'basicWhereAmI', etc. + """ + try: + return self[args['mode']][args['role']][args['formatType']] + except Exception: + pass + + if args.get('formatType') == 'ancestor': + try: + return self[args['mode']][args['role']]['focused'] + except Exception: + pass + + if args.get('formatType') == 'detailedWhereAmI': + try: + return self[args['mode']][args['role']]['basicWhereAmI'] + except Exception: + pass + + try: + return self[args['mode']][args['role']]['unfocused'] + except Exception: + pass + + + try: + return self[args['mode']]['default'][args['formatType']] + except Exception: + pass + + try: + return self[args['mode']]['default']['unfocused'] + except Exception: + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/generator.py new file mode 100644 index 0000000..fe86343 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/generator.py @@ -0,0 +1,1528 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Superclass of classes used to generate presentations for objects.""" + +__id__ = "$Id:$" +__version__ = "$Revision:$" +__date__ = "$Date:$" +__copyright__ = "Copyright (c) 2009 Sun Microsystems Inc." \ + "Copyright (c) 2015-2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +gi.require_version('Atk', '1.0') +from gi.repository import Atk + +import re +import sys +import time +import traceback + +from . import braille +from . import debug +from . import messages +from . import object_properties +from . import settings +from . import settings_manager +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +# Python 3.10 compatibility: +try: + import collections.abc as collections_abc +except ImportError: + import collections as collections_abc + +def _formatExceptionInfo(maxTBlevel=5): + cla, exc, trbk = sys.exc_info() + excName = cla.__name__ + try: + excArgs = exc.args + except KeyError: + excArgs = "" + excTb = traceback.format_tb(trbk, maxTBlevel) + return (excName, excArgs, excTb) + +# [[[WDW - general note -- for all the _generate* methods, it would be great if +# we could return an empty array if we can determine the method does not +# apply to the object. This would allow us to reduce the number of strings +# needed in formatting.py.]]] + +# The prefix to use for the individual generator methods +# +METHOD_PREFIX = "_generate" + +_settingsManager = settings_manager.getManager() + +class Generator: + """Takes accessible objects and generates a presentation for those + objects. See the generate method, which is the primary entry + point.""" + + def __init__(self, script, mode): + self._mode = mode + self._script = script + self._activeProgressBars = {} + self._methodsDict = {} + for method in \ + [z for z in [getattr(self, y).__get__(self, self.__class__) \ + for y in [x for x in dir(self) if x.startswith(METHOD_PREFIX)]] \ + if isinstance(z, collections_abc.Callable)]: + name = method.__name__[len(METHOD_PREFIX):] + name = name[0].lower() + name[1:] + self._methodsDict[name] = method + self._verifyFormatting() + + def _addGlobals(self, globalsDict): + """Other things to make available from the formatting string. + """ + globalsDict['obj'] = None + globalsDict['role'] = None + + def _verifyFormatting(self): + + # Verify the formatting strings are OK. This is only + # for verification and does not effect the function of + # Cthulhu at all. + + # Populate the entire globals with empty arrays + # for the results of all the legal method names. + # + globalsDict = {} + for key in self._methodsDict.keys(): + globalsDict[key] = [] + self._addGlobals(globalsDict) + + for roleKey in self._script.formatting[self._mode]: + for key in ["focused", "unfocused"]: + try: + evalString = \ + self._script.formatting[self._mode][roleKey][key] + except Exception: + continue + else: + if not evalString: + # It's legal to have an empty string. + # + continue + while True: + try: + eval(evalString, globalsDict) + break + except NameError: + info = _formatExceptionInfo() + arg = info[1][0] + arg = arg.replace("name '", "") + arg = arg.replace("' is not defined", "") + if arg not in self._methodsDict: + debug.printException(debug.LEVEL_SEVERE) + globalsDict[arg] = [] + except Exception: + debug.printException(debug.LEVEL_SEVERE) + break + + def _overrideRole(self, newRole, args): + """Convenience method to allow you to temporarily override the role in + the args dictionary. This changes the role in args ags + returns the old role so you can pass it back to _restoreRole. + """ + oldRole = args.get('role', None) + args['role'] = newRole + return oldRole + + def _restoreRole(self, oldRole, args): + """Convenience method to restore the old role back in the args + dictionary. The oldRole should have been obtained from + _overrideRole. If oldRole is None, then the 'role' key/value + pair will be deleted from args. + """ + if oldRole: + args['role'] = oldRole + else: + del args['role'] + + def generateContents(self, contents, **args): + return [] + + def generateContext(self, obj, **args): + return [] + + def generate(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the complete presentation for the + object. The presentation to be generated depends highly upon the + formatting strings in formatting.py. + + args is a dictionary that may contain any of the following: + - alreadyFocused: if True, we're getting an object + that previously had focus + - priorObj: if set, represents the object that had focus before + this object + - includeContext: boolean (default=True) which says whether + the context for an object should be included as a prefix + and suffix + - role: a role to override the object's role + - formatType: the type of formatting, such as + 'focused', 'basicWhereAmI', etc. + - forceMnemonic: boolean (default=False) which says if we + should ignore the settings.enableMnemonicSpeaking setting + - forceTutorial: boolean (default=False) which says if we + should force a tutorial to be spoken or not + """ + + if AXObject.is_dead(obj): + msg = "GENERATOR: Cannot generate presentation for dead obj" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return [] + + startTime = time.time() + result = [] + globalsDict = {} + self._addGlobals(globalsDict) + globalsDict['obj'] = obj + try: + globalsDict['role'] = args.get('role', AXObject.get_role(obj)) + except Exception as error: + tokens = ["GENERATOR: Cannot generate presentation for", obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + try: + # We sometimes want to override the role. We'll keep the + # role in the args dictionary as a means to let us do so. + # + args['role'] = globalsDict['role'] + + # We loop through the format string, catching each error + # as we go. Each error should always be a NameError, + # where the name is the name of one of our generator + # functions. When we encounter this, we call the function + # and get its results, placing them in the globals for the + # the call to eval. + # + args['mode'] = self._mode + if not args.get('formatType', None): + if args.get('alreadyFocused', False): + args['formatType'] = 'focused' + else: + args['formatType'] = 'unfocused' + + formatting = self._script.formatting.getFormat(**args) + + # Add in the context if this is the first time + # we've been called. + # + if not args.get('recursing', False): + if args.get('includeContext', True): + prefix = self._script.formatting.getPrefix(**args) + suffix = self._script.formatting.getSuffix(**args) + formatting = f'{prefix} + {formatting} + {suffix}' + args['recursing'] = True + + tokens = [self._mode.upper(), "GENERATOR: Starting", args.get('formatType'), + "generation for", obj, "(using role:", args.get('role'), ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # Reset 'usedDescriptionFor*' if a previous generator used it. + self._script.pointOfReference['usedDescriptionForName'] = False + self._script.pointOfReference['usedDescriptionForUnrelatedLabels'] = False + self._script.pointOfReference['usedDescriptionForAlert'] = False + + def debuginfo(x): + return self._resultElementToString(x, False) + + assert(formatting) + while True: + currentTime = time.time() + try: + result = eval(formatting, globalsDict) + break + except NameError: + result = [] + info = _formatExceptionInfo() + arg = info[1][0] + arg = arg.replace("name '", "") + arg = arg.replace("' is not defined", "") + if arg not in self._methodsDict: + debug.printException(debug.LEVEL_SEVERE) + break + globalsDict[arg] = self._methodsDict[arg](obj, **args) + duration = f"{time.time() - currentTime:.4f}" + if isinstance(globalsDict[arg], list): + stringResult = " ".join(filter(lambda x: x, + map(debuginfo, globalsDict[arg]))) + debug.printMessage(debug.LEVEL_ALL, + "%sGENERATION TIME: %s ----> %s=[%s]" \ + % (" " * 18, duration, arg, stringResult)) + + except Exception: + debug.printException(debug.LEVEL_SEVERE) + result = [] + + duration = f"{time.time() - startTime:.4f}" + debug.printMessage(debug.LEVEL_ALL, f"{' ' * 18}COMPLETION TIME: {duration}") + self._debugResultInfo(result) + if args.get('isProgressBarUpdate') and result and result[0]: + self.setProgressBarUpdateTimeAndValue(obj) + + return result + + def _resultElementToString(self, element, includeAll=True): + if not includeAll: + return str(element).replace("\n", "\\n") + + return f"\n{' ' * 18}'{element}'" + + def _debugResultInfo(self, result): + if debug.LEVEL_ALL < debug.debugLevel: + return + + info = f"{' ' * 18}{self._mode.upper()} GENERATOR: Results: " + info += f"{' '.join(map(self._resultElementToString, result))}" + debug.printMessage(debug.LEVEL_ALL, info) + + ##################################################################### + # # + # Name, role, and label information # + # # + ##################################################################### + + def _generateRoleName(self, obj, **args): + """Returns the role name for the object in an array of strings, with + the exception that the Atspi.Role.UNKNOWN role will yield an + empty array. Note that a 'role' attribute in args will + override the accessible role of the obj. + """ + # Subclasses must override this. + return [] + + def _fallBackOnDescriptionForName(self, obj, **args): + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.LABEL: + return False + + return True + + def _generateName(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the name of the object. If the object is directly + displaying any text, that text will be treated as the name. + Otherwise, the accessible name of the object will be used. If + there is no accessible name, then the description of the + object will be used. This method will return an empty array + if nothing can be found. [[[WDW - I wonder if we should just + have _generateName, _generateDescription, + _generateDisplayedText, etc., that don't do any fallback. + Then, we can allow the formatting to do the fallback (e.g., + 'displayedText or name or description'). [[[JD to WDW - I + needed a _generateDescription for whereAmI. :-) See below. + """ + result = [] + self._script.pointOfReference['usedDescriptionForName'] = False + name = AXObject.get_name(obj) + role = args.get('role', AXObject.get_role(obj)) + parent = AXObject.get_parent(obj) + if name: + result.append(name) + elif self._fallBackOnDescriptionForName(obj, **args): + description = AXObject.get_description(obj) + if description: + result.append(description) + self._script.pointOfReference['usedDescriptionForName'] = True + else: + link = None + if role == Atspi.Role.LINK: + link = obj + elif AXUtilities.is_link(parent): + link = parent + if link: + basename = self._script.utilities.linkBasenameToName(link) + if basename: + result.append(basename) + # To make the unlabeled icons in gnome-panel more accessible. + if not result and role == Atspi.Role.ICON and AXUtilities.is_panel(parent): + return self._generateName(parent) + + return result + + def _generatePlaceholderText(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the 'placeholder' text. This is typically text that + serves as a functional label and is found in a text widget until + that widget is given focus at which point the text is removed, + the assumption being that the user was able to see the text prior + to giving the widget focus. + """ + attrs = self._script.utilities.objectAttributes(obj) + placeholder = attrs.get('placeholder-text') + if placeholder and placeholder != AXObject.get_name(obj): + return [placeholder] + + placeholder = attrs.get('placeholder') + if placeholder and placeholder != AXObject.get_name(obj): + return [placeholder] + + return [] + + def _generateLabelAndName(self, obj, **args): + """Returns the label and the name as an array of strings for speech + and braille. The name will only be present if the name is + different from the label. + """ + result = [] + label = self._generateLabel(obj, **args) + name = self._generateName(obj, **args) + role = args.get('role', AXObject.get_role(obj)) + if not (label or name) and role == Atspi.Role.TABLE_CELL: + descendant = self._script.utilities.realActiveDescendant(obj) + name = self._generateName(descendant) + + # If we don't have a label, always use the name. + if not label: + return name + + result.extend(label) + if not name: + return result + + # Try to eliminate names which are redundant to the label. + # Convert all non-alphanumeric characters to space and get the words. + nameWords = re.sub(r"[\W_]", " ", name[0]).split() + labelWords = re.sub(r"[\W_]", " ", label[0]).split() + + # If all of the words in the name are in the label, the name is redundant. + if set(nameWords).issubset(set(labelWords)): + tokens = ["GENERATOR: name '", name[0], "' is redundant to label '", label[0], "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + result.extend(name) + return result + + def _generateLabelOrName(self, obj, **args): + """Returns the label as an array of strings for speech and braille. + If the label cannot be found, the name will be used instead. + If the name cannot be found, an empty array will be returned. + """ + result = self._generateLabel(obj, **args) + if not result: + result = self._generateName(obj, **args) + + return result + + def _generateUnrelatedLabelsOrDescription(self, obj, **args): + result = self._generateUnrelatedLabels(obj, **args) + if result: + self._script.pointOfReference['usedDescriptionForUnrelatedLabels'] = False + return result + + result = self._generateDescription(obj, **args) + if result: + self._script.pointOfReference['usedDescriptionForUnrelatedLabels'] = True + + return result + + def _generateDescription(self, obj, **args): + """Returns an array of strings fo use by speech and braille that + represent the description of the object, if that description + is different from that of the name and label. + """ + + if self._script.pointOfReference.get('usedDescriptionForName'): + return [] + + if self._script.pointOfReference.get('usedDescriptionForAlert'): + return [] + + if self._script.pointOfReference.get('usedDescriptionForUnrelatedLabels'): + return [] + + description = AXObject.get_description(obj) \ + or self._script.utilities.displayedDescription(obj) or "" + if not description: + return [] + + name = AXObject.get_name(obj) + role = args.get('role', AXObject.get_role(obj)) + + try: + tokens = self._script.formatting[self._mode][role][args.get('formatType')].split() + isLabelAndName = 'labelAndName' in tokens + isLabelOrName = 'labelOrName' in tokens + except Exception: + isLabelAndName = False + isLabelOrName = False + + canUse = True + label = self._script.utilities.displayedLabel(obj) or "" + if isLabelAndName: + canUse = not self._script.utilities.stringsAreRedundant(name, description) \ + and not self._script.utilities.stringsAreRedundant(label, description) + elif isLabelOrName and label: + canUse = not self._script.utilities.stringsAreRedundant(label, description) + else: + canUse = not self._script.utilities.stringsAreRedundant(name, description) + + if not canUse: + return [] + + return [description] + + def _generateLabel(self, obj, **args): + """Returns the label for an object as an array of strings for use by + speech and braille. The label is determined by the displayedLabel + method of the script utility, and an empty array will be returned if + no label can be found. + """ + result = [] + label = self._script.utilities.displayedLabel(obj) + if label: + result.append(label) + return result + + def _generateStatusBar(self, obj, **args): + """Returns an array of strings that represent a status bar.""" + + return [] + + def _generateTermValueCount(self, obj, **args): + return [] + + ##################################################################### + # # + # Image information # + # # + ##################################################################### + + def _generateImageDescription(self, obj, **args ): + """Returns an array of strings for use by speech and braille that + represent the description of the image on the object, if it + exists. Otherwise, an empty array is returned. + """ + result = [] + try: + image = obj.queryImage() + except NotImplementedError: + pass + else: + description = image.imageDescription + if description and len(description): + result.append(description) + return result + + ##################################################################### + # # + # State information # + # # + ##################################################################### + + def _generateClickable(self, obj, **args): + return [] + + def _generateHasLongDesc(self, obj, **args): + return [] + + def _generateHasDetails(self, obj, **args): + return [] + + def _generateDetailsFor(self, obj, **args): + return [] + + def _generateAllDetails(self, obj, **args): + return [] + + def _generateHasPopup(self, obj, **args): + return [] + + def _generateAvailability(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the grayed/sensitivity/availability state of the + object, but only if it is insensitive (i.e., grayed out and + inactive). Otherwise, and empty array will be returned. + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'insensitive' + if not AXUtilities.is_sensitive(obj): + result.append(self._script.formatting.getString(**args)) + return result + + def _generateInvalid(self, obj, **args): + error = self._script.utilities.getError(obj) + if not error: + return [] + + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'invalid' + indicators = self._script.formatting.getString(**args) + + if error == 'spelling': + indicator = indicators[1] + elif error == 'grammar': + indicator = indicators[2] + else: + indicator = indicators[0] + + errorMessage = self._script.utilities.getErrorMessage(obj) + if errorMessage: + result.append(f"{indicator}: {errorMessage}") + else: + result.append(indicator) + + return result + + def _generateRequired(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the required state of the object, but only if it is + required (i.e., it is in a dialog requesting input and the + user must give it a value). Otherwise, and empty array will + be returned. + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'required' + isRequired = AXUtilities.is_required(obj) + if not isRequired and AXUtilities.is_radio_button(obj): + parent = AXObject.get_parent(obj) + isRequired = AXUtilities.is_required(parent) + if isRequired: + result.append(self._script.formatting.getString(**args)) + return result + + def _generateReadOnly(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the read only state of this object, but only if it + is read only (i.e., it is a text area that cannot be edited). + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'readonly' + if AXUtilities.is_read_only(obj) \ + or self._script.utilities.isReadOnlyTextArea(obj): + result.append(self._script.formatting.getString(**args)) + return result + + def _generateCellCheckedState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes that are in a table. An empty array will be + returned if this is not a checkable cell. + """ + result = [] + if self._script.utilities.hasMeaningfulToggleAction(obj): + oldRole = self._overrideRole(Atspi.Role.CHECK_BOX, args) + result.extend(self.generate(obj, **args)) + self._restoreRole(oldRole, args) + + return result + + def _generateCheckedState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes. [[[WDW - should we return an empty array if + we can guarantee we know this thing is not checkable?]]] + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'checkbox' + indicators = self._script.formatting.getString(**args) + if AXUtilities.is_checked(obj): + result.append(indicators[1]) + elif AXUtilities.is_indeterminate(obj): + result.append(indicators[2]) + else: + result.append(indicators[0]) + return result + + def _generateRadioState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes. [[[WDW - should we return an empty array if + we can guarantee we know this thing is not checkable?]]] + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'radiobutton' + indicators = self._script.formatting.getString(**args) + if AXUtilities.is_checked(obj): + result.append(indicators[1]) + else: + result.append(indicators[0]) + return result + + def _generateChildWidget(self, obj, **args): + widgetRoles = [Atspi.Role.CHECK_BOX, + Atspi.Role.COMBO_BOX, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.SLIDER, + Atspi.Role.TOGGLE_BUTTON] + + def isWidget(x): + return AXObject.get_role(x) in widgetRoles + + # For GtkListBox, such as those found in the control center + if AXUtilities.is_list_box(AXObject.get_parent(obj)): + widget = AXObject.find_descendant(obj, isWidget) + if widget: + return self.generate(widget, includeContext=False) + + return [] + + def _generateSwitchState(self, obj, **args): + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'switch' + indicators = self._script.formatting.getString(**args) + if AXUtilities.is_checked(obj) or AXUtilities.is_pressed(obj): + result.append(indicators[1]) + else: + result.append(indicators[0]) + return result + + def _generateToggleState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes. [[[WDW - should we return an empty array if + we can guarantee we know this thing is not checkable?]]] + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'togglebutton' + indicators = self._script.formatting.getString(**args) + if AXUtilities.is_checked(obj) or AXUtilities.is_pressed(obj): + result.append(indicators[1]) + else: + result.append(indicators[0]) + return result + + def _generateCheckedStateIfCheckable(self, obj, **args): + if AXUtilities.is_checkable(obj) or AXUtilities.is_check_menu_item(obj): + return self._generateCheckedState(obj, **args) + + if AXUtilities.is_checked(obj): + return self._generateCheckedState(obj, **args) + + return [] + + def _generateMenuItemCheckedState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the menu item, only if it is + checked. Otherwise, and empty array will be returned. + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'checkbox' + indicators = self._script.formatting.getString(**args) + if AXUtilities.is_checked(obj): + result.append(indicators[1]) + return result + + def _generateExpandableState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the expanded/collapsed state of an object, such as a + tree node. If the object is not expandable, an empty array + will be returned. + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'expansion' + indicators = self._script.formatting.getString(**args) + if AXUtilities.is_collapsed(obj): + result.append(indicators[0]) + elif AXUtilities.is_expanded(obj): + result.append(indicators[1]) + elif AXUtilities.is_expandable(obj): + result.append(indicators[0]) + + return result + + def _generateMultiselectableState(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the multiselectable state of + the object. This is typically for list boxes. If the object + is not multiselectable, an empty array will be returned. + """ + + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'multiselect' + if AXUtilities.is_multiselectable(obj) and AXObject.get_child_count(obj): + result.append(self._script.formatting.getString(**args)) + return result + + ##################################################################### + # # + # Table interface information # + # # + ##################################################################### + + def _generateRowHeader(self, obj, **args): + """Returns an array of strings to be used in speech and braille that + represent the row header for an object that is in a table, if + it exists. Otherwise, an empty array is returned. + """ + + if args.get('readingRow'): + return [] + + result = [] + header = self._script.utilities.rowHeaderForCell(obj) + if not header: + return result + + text = self._script.utilities.displayedText(header) + if not text: + return result + + roleString = self.getLocalizedRoleName(obj, role=Atspi.Role.ROW_HEADER) + if args.get('mode') == 'speech': + if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \ + and args.get('formatType') not in ['basicWhereAmI', 'detailedWhereAmI']: + text = f"{text} {roleString}" + elif args.get('mode') == 'braille': + text = f"{text} {roleString}" + + result.append(text) + return result + + def _generateColumnHeader(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the column header for an object + that is in a table, if it exists. Otherwise, an empty array + is returned. + """ + result = [] + header = self._script.utilities.columnHeaderForCell(obj) + if not header: + return result + + text = self._script.utilities.displayedText(header) + if not text: + return result + + roleString = self.getLocalizedRoleName(obj, role=Atspi.Role.COLUMN_HEADER) + if args.get('mode') == 'speech': + if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \ + and args.get('formatType') not in ['basicWhereAmI', 'detailedWhereAmI']: + text = f"{text} {roleString}" + elif args.get('mode') == 'braille': + text = f"{text} {roleString}" + + result.append(text) + return result + + def _generateSortOrder(self, obj, **args): + description = self._script.utilities.getSortOrderDescription(obj) + if not description: + return [] + + return [description] + + def _generateTableCell2ChildLabel(self, obj, **args): + """Returns an array of strings for use by speech and braille for the + label of a toggle in a table cell that has a special 2 child + pattern that we run into. Otherwise, an empty array is + returned. + """ + result = [] + + # If this table cell has 2 children and one of them has a + # 'toggle' action and the other does not, then present this + # as a checkbox where: + # 1) we get the checked state from the cell with the 'toggle' action + # 2) we get the label from the other cell. + # See Cthulhu bug #376015 for more details. + # + if AXObject.get_child_count(obj) == 2: + cellOrder = [] + hasToggle = [False, False] + for i, child in enumerate(obj): + if self._script.utilities.hasMeaningfulToggleAction(child): + hasToggle[i] = True + break + if hasToggle[0] and not hasToggle[1]: + cellOrder = [ 1, 0 ] + elif not hasToggle[0] and hasToggle[1]: + cellOrder = [ 0, 1 ] + if cellOrder: + for i in cellOrder: + if not hasToggle[i]: + result.extend(self.generate(AXObject.get_child(obj, i), **args)) + return result + + def _generateTableCell2ChildToggle(self, obj, **args): + """Returns an array of strings for use by speech and braille for the + toggle value of a toggle in a table cell that has a special 2 + child pattern that we run into. Otherwise, an empty array is + returned. + """ + result = [] + + # If this table cell has 2 children and one of them has a + # 'toggle' action and the other does not, then present this + # as a checkbox where: + # 1) we get the checked state from the cell with the 'toggle' action + # 2) we get the label from the other cell. + # See Cthulhu bug #376015 for more details. + # + if AXObject.get_child_count(obj) == 2: + cellOrder = [] + hasToggle = [False, False] + for i, child in enumerate(obj): + if self._script.utilities.hasMeaningfulToggleAction(child): + hasToggle[i] = True + break + if hasToggle[0] and not hasToggle[1]: + cellOrder = [ 1, 0 ] + elif not hasToggle[0] and hasToggle[1]: + cellOrder = [ 0, 1 ] + if cellOrder: + for i in cellOrder: + if hasToggle[i]: + result.extend(self.generate(AXObject.get_child(obj, i), **args)) + return result + + def _generateColumnHeaderIfToggleAndNoText(self, obj, **args): + """If this table cell has a "toggle" action, and doesn't have any + label associated with it then also speak the table column + header. See Cthulhu bug #455230 for more details. + """ + # If we're reading just a single cell in speech, the new + # header portion is going to give us this information. + # + if args['mode'] == 'speech' and not args.get('readingRow', False): + return [] + + result = [] + descendant = self._script.utilities.realActiveDescendant(obj) + label = self._script.utilities.displayedText(descendant) + if not label and self._script.utilities.hasMeaningfulToggleAction(obj): + accHeader = self._script.utilities.columnHeaderForCell(obj) + if (accHeader): + result.append(AXObject.get_name(accHeader)) + return result + + def _generateRealTableCell(self, obj, **args): + """Cthulhu has a feature to automatically read an entire row of a table + as the user arrows up/down the roles. This leads to + complexity in the code. This method is used to return an + array of strings for use by speech and braille for a single + table cell itself. The string, 'blank', is added for empty + cells. + """ + result = [] + oldRole = self._overrideRole('REAL_ROLE_TABLE_CELL', args) + result.extend(self.generate(obj, **args)) + self._restoreRole(oldRole, args) + return result + + def _generateTable(self, obj, **args): + """Returns an array of strings for use by speech and braille to present + the size of a table.""" + + if self._script.utilities.isLayoutOnly(obj): + return [] + + if self._script.utilities.isSpreadSheetTable(obj): + return [] + + rows, cols = self._script.utilities.rowAndColumnCount(obj) + + # This suggests broken or missing table interface. + if (rows < 0 or cols < 0) \ + and not self._script.utilities.rowOrColumnCountUnknown(obj): + return [] + + # This can happen if an author uses ARIA incorrectly, e.g. a grid whose + # immediate child is a gridcell rather than a row. In that case, just + # announce the role name. + if rows == 0 and cols == 0: + return self._generateRoleName(obj, **args) + + return [messages.tableSize(rows, cols)] + + def _generateTableCellRow(self, obj, **args): + """Cthulhu has a feature to automatically read an entire row of a table + as the user arrows up/down the roles. This leads to complexity in + the code. This method is used to return an array of strings + (and possibly voice and audio specifications) for an entire row + in a table if that's what the user has requested and if the row + has changed. Otherwise, it will return an array for just the + current cell. + """ + + presentAll = args.get('readingRow') is True \ + or args.get('formatType') == 'detailedWhereAmI' \ + or self._mode == 'braille' \ + or self._script.utilities.shouldReadFullRow(obj) + + if not presentAll: + return self._generateRealTableCell(obj, **args) + + args['readingRow'] = True + result = [] + cells = self._script.utilities.getShowingCellsInSameRow(obj, forceFullRow=True) + + # Remove any pre-calcuated values which only apply to obj and not row cells. + doNotInclude = ['startOffset', 'endOffset', 'string'] + otherCellArgs = args.copy() + for arg in doNotInclude: + otherCellArgs.pop(arg, None) + + for cell in cells: + if cell == obj: + cellResult = self._generateRealTableCell(cell, **args) + else: + cellResult = self._generateRealTableCell(cell, **otherCellArgs) + if cellResult and result and self._mode == 'braille': + result.append(braille.Region(object_properties.TABLE_CELL_DELIMITER_BRAILLE)) + result.extend(cellResult) + + result.extend(self._generatePositionInList(obj, **args)) + return result + + ##################################################################### + # # + # Text interface information # + # # + ##################################################################### + + def _generateExpandedEOCs(self, obj, **args): + """Returns the expanded embedded object characters for an object.""" + return [] + + def _generateSubstring(self, obj, **args): + start = args.get('startOffset') + end = args.get('endOffset') + if start is None or end is None: + return [] + + substring = args.get('string', self._script.utilities.substring(obj, start, end)) + if substring and self._script.EMBEDDED_OBJECT_CHARACTER not in substring: + return [substring] + + return [] + + def _generateStartOffset(self, obj, **args): + return args.get('startOffset') + + def _generateEndOffset(self, obj, **args): + return args.get('endOffset') + + def _generateCurrentLineText(self, obj, **args ): + """Returns an array of strings for use by speech and braille + that represents the current line of text, if + this is a text object. [[[WDW - consider returning an empty + array if this is not a text object.]]] + """ + result = self._generateSubstring(obj, **args) + if result: + return result + + [text, caretOffset, startOffset] = self._script.getTextLineAtCaret(obj) + if text and self._script.EMBEDDED_OBJECT_CHARACTER not in text: + return [text] + + return [] + + def _generateDisplayedText(self, obj, **args ): + """Returns an array of strings for use by speech and braille that + represents all the text being displayed by the object. + """ + result = self._generateSubstring(obj, **args) + if result: + return result + + displayedText = self._script.utilities.displayedText(obj) + if not displayedText: + return [] + + return [displayedText] + + ##################################################################### + # # + # Tree interface information # + # # + ##################################################################### + + def _generateNodeLevel(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represents the tree node level of the object, or an empty + array if the object is not a tree node. + """ + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'nodelevel' + level = self._script.utilities.nodeLevel(obj) + if level >= 0: + result.append(self._script.formatting.getString(**args)\ + % (level + 1)) + return result + + ##################################################################### + # # + # Value interface information # + # # + ##################################################################### + + def _generateValue(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represents the value of the object. This is typically the + numerical value, but may also be the text of the 'value' + attribute if it exists on the object. [[[WDW - we should + consider returning an empty array if there is no value. + """ + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.COMBO_BOX: + value = self._script.utilities.getComboBoxValue(obj) + return [value] + + if role == Atspi.Role.SEPARATOR and not AXUtilities.is_focused(obj): + return [] + + return [self._script.utilities.textForValue(obj)] + + ##################################################################### + # # + # Hierarchy and related dialog information # + # # + ##################################################################### + + def _generateApplicationName(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represents the name of the application for the object. + """ + result = [] + name = AXObject.get_name(AXObject.get_application(obj)) + if name: + result.append(name) + return result + + def _generateNestingLevel(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the nesting level of an object in a list. + """ + start = args.get('startOffset') + end = args.get('endOffset') + if start is not None and end is not None: + return [] + + result = [] + if not args.get('mode', None): + args['mode'] = self._mode + args['stringType'] = 'nestinglevel' + nestingLevel = self._script.utilities.nestingLevel(obj) + if nestingLevel: + result.append(self._script.formatting.getString(**args)\ + % nestingLevel) + return result + + def _generateRadioButtonGroup(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represents the radio button group label for the object, or an + empty array if the object has no such label. + """ + if not AXUtilities.is_radio_button(obj): + return [] + + radioGroupLabel = None + relation = AXObject.get_relation(obj, Atspi.RelationType.LABELLED_BY) + if relation: + radioGroupLabel = relation.get_target(0) + if radioGroupLabel: + return [self._script.utilities.displayedText(radioGroupLabel)] + + parent = AXObject.get_parent_checked(obj) + while parent: + if AXUtilities.is_panel(parent) or AXUtilities.is_filler(parent): + label = self._generateLabelAndName(parent) + if label: + return label + parent = AXObject.get_parent_checked(parent) + return [] + + def _generateRealActiveDescendantDisplayedText(self, obj, **args ): + """Objects, such as tables and trees, can represent individual cells + via a complicated nested hierarchy. This method returns an + array of strings for use by speech and braille that represents + the text actually being painted in the cell, if it can be + found. Otherwise, an empty array is returned. + """ + rad = self._script.utilities.realActiveDescendant(obj) + + if not (AXUtilities.is_table_cell(rad) and AXObject.get_child_count(rad)): + return self._generateDisplayedText(rad, **args) + + content = set([self._script.utilities.displayedText(x).strip() for x in rad]) + rv = " ".join(filter(lambda x: x, content)) + if not rv: + return self._generateDisplayedText(rad, **args) + return [rv] + + def _generateRealActiveDescendantRoleName(self, obj, **args ): + """Objects, such as tables and trees, can represent individual cells + via a complicated nested hierarchy. This method returns an + array of strings for use by speech and braille that represents + the role of the object actually being painted in the cell. + """ + rad = self._script.utilities.realActiveDescendant(obj) + args['role'] = AXObject.get_role(rad) + return self._generateRoleName(rad, **args) + + def _generateNamedContainingPanel(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represents the nearest ancestor of an object which is a named panel. + """ + result = [] + parent = AXObject.get_parent_checked(obj) + while parent: + if AXUtilities.is_panel(parent): + label = self._generateLabelAndName(parent) + if label: + result.extend(label) + break + parent = AXObject.get_parent_checked(parent) + return result + + def _generatePageSummary(self, obj, **args): + return [] + + def _generatePositionInList(self, obj, **args): + return [] + + def _generateProgressBarIndex(self, obj, **args): + return [] + + def _generateProgressBarValue(self, obj, **args): + return [] + + def _getProgressBarUpdateInterval(self): + return int(_settingsManager.getSetting('progressBarUpdateInterval')) + + def _shouldPresentProgressBarUpdate(self, obj, **args): + percent = self._script.utilities.getValueAsPercent(obj) + lastTime, lastValue = self.getProgressBarUpdateTimeAndValue(obj, type=self) + if percent == lastValue: + tokens = ["GENERATOR: Not presenting update for", obj, ". Value still", percent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if percent == 100: + return True + + interval = int(time.time() - lastTime) + return interval >= self._getProgressBarUpdateInterval() + + def _cleanUpCachedProgressBars(self): + def isValid(x): + return not (self._script.utilities.isZombie(x) or AXObject.is_dead(x)) + + bars = list(filter(isValid, self._activeProgressBars)) + self._activeProgressBars = {x:self._activeProgressBars.get(x) for x in bars} + + def _getMostRecentProgressBarUpdate(self): + self._cleanUpCachedProgressBars() + if not self._activeProgressBars.values(): + return None, 0.0, None + + sortedValues = sorted(self._activeProgressBars.values(), key=lambda x: x[0]) + prevTime, prevValue = sortedValues[-1] + return list(self._activeProgressBars.keys())[-1], prevTime, prevValue + + def getProgressBarNumberAndCount(self, obj): + self._cleanUpCachedProgressBars() + if obj not in self._activeProgressBars: + self._activeProgressBars[obj] = 0.0, None + + thisValue = self.getProgressBarUpdateTimeAndValue(obj) + index = list(self._activeProgressBars.values()).index(thisValue) + return index + 1, len(self._activeProgressBars) + + def getProgressBarUpdateTimeAndValue(self, obj, **args): + if obj not in self._activeProgressBars: + self._activeProgressBars[obj] = 0.0, None + + return self._activeProgressBars.get(obj) + + def setProgressBarUpdateTimeAndValue(self, obj, lastTime=None, lastValue=None): + lastTime = lastTime or time.time() + lastValue = lastValue or self._script.utilities.getValueAsPercent(obj) + self._activeProgressBars[obj] = lastTime, lastValue + + def _getAlternativeRole(self, obj, **args): + if self._script.utilities.isMath(obj): + if self._script.utilities.isMathSubOrSuperScript(obj): + return 'ROLE_MATH_SCRIPT_SUBSUPER' + if self._script.utilities.isMathUnderOrOverScript(obj): + return 'ROLE_MATH_SCRIPT_UNDEROVER' + if self._script.utilities.isMathMultiScript(obj): + return 'ROLE_MATH_MULTISCRIPT' + if self._script.utilities.isMathEnclose(obj): + return 'ROLE_MATH_ENCLOSED' + if self._script.utilities.isMathFenced(obj): + return 'ROLE_MATH_FENCED' + if self._script.utilities.isMathTable(obj): + return 'ROLE_MATH_TABLE' + if self._script.utilities.isMathTableRow(obj): + return 'ROLE_MATH_TABLE_ROW' + if self._script.utilities.isDPub(obj): + if self._script.utilities.isLandmark(obj): + return 'ROLE_DPUB_LANDMARK' + if AXUtilities.is_section(obj): + return 'ROLE_DPUB_SECTION' + if self._script.utilities.isSwitch(obj): + return 'ROLE_SWITCH' + if self._script.utilities.isAnchor(obj): + return Atspi.Role.STATIC + if self._script.utilities.isBlockquote(obj): + return Atspi.Role.BLOCK_QUOTE + if self._script.utilities.isComment(obj): + return Atspi.Role.COMMENT + if self._script.utilities.isContentDeletion(obj): + return 'ROLE_CONTENT_DELETION' + if self._script.utilities.isContentError(obj): + return 'ROLE_CONTENT_ERROR' + if self._script.utilities.isContentInsertion(obj): + return 'ROLE_CONTENT_INSERTION' + if self._script.utilities.isContentMarked(obj): + return 'ROLE_CONTENT_MARK' + if self._script.utilities.isContentSuggestion(obj): + return 'ROLE_CONTENT_SUGGESTION' + if self._script.utilities.isDescriptionList(obj): + return Atspi.Role.DESCRIPTION_LIST + if self._script.utilities.isDescriptionListTerm(obj): + return Atspi.Role.DESCRIPTION_TERM + if self._script.utilities.isDescriptionListDescription(obj): + return Atspi.Role.DESCRIPTION_VALUE + if self._script.utilities.isFeedArticle(obj): + return 'ROLE_ARTICLE_IN_FEED' + if self._script.utilities.isFeed(obj): + return 'ROLE_FEED' + if self._script.utilities.isLandmark(obj): + if self._script.utilities.isLandmarkRegion(obj): + return 'ROLE_REGION' + return Atspi.Role.LANDMARK + if self._script.utilities.isFocusableLabel(obj): + return Atspi.Role.LIST_ITEM + if self._script.utilities.isDocument(obj) and AXObject.supports_image(obj): + return Atspi.Role.IMAGE + + return args.get('role', AXObject.get_role(obj)) + + def getLocalizedRoleName(self, obj, **args): + role = args.get('role', AXObject.get_role(obj)) + + if AXObject.supports_value(obj): + if AXUtilities.is_horizontal_slider(obj): + return object_properties.ROLE_SLIDER_HORIZONTAL + if AXUtilities.is_vertical_slider(obj): + return object_properties.ROLE_SLIDER_VERTICAL + if AXUtilities.is_horizontal_scrollbar(obj): + return object_properties.ROLE_SCROLL_BAR_HORIZONTAL + if AXUtilities.is_vertical_scrollbar(obj): + return object_properties.ROLE_SCROLL_BAR_VERTICAL + if AXUtilities.is_horizontal_separator(obj): + return object_properties.ROLE_SPLITTER_HORIZONTAL + if AXUtilities.is_vertical_separator(obj): + return object_properties.ROLE_SPLITTER_VERTICAL + if AXUtilities.is_split_pane(obj) \ + and (AXUtilities.is_focused(obj) or args.get('alreadyFocused', False)): + # The splitter has the opposite orientation of the split pane. + if AXUtilities.is_horizontal(obj): + return object_properties.ROLE_SPLITTER_VERTICAL + if AXUtilities.is_vertical(obj): + return object_properties.ROLE_SPLITTER_HORIZONTAL + + if self._script.utilities.isContentSuggestion(obj): + return object_properties.ROLE_CONTENT_SUGGESTION + + if self._script.utilities.isFeed(obj): + return object_properties.ROLE_FEED + + if self._script.utilities.isFigure(obj): + return object_properties.ROLE_FIGURE + + if self._script.utilities.isMenuButton(obj): + return object_properties.ROLE_MENU_BUTTON + + if self._script.utilities.isSwitch(obj): + return object_properties.ROLE_SWITCH + + if self._script.utilities.isDPub(obj): + if self._script.utilities.isLandmark(obj): + if self._script.utilities.isDPubAcknowledgments(obj): + return object_properties.ROLE_ACKNOWLEDGMENTS + if self._script.utilities.isDPubAfterword(obj): + return object_properties.ROLE_AFTERWORD + if self._script.utilities.isDPubAppendix(obj): + return object_properties.ROLE_APPENDIX + if self._script.utilities.isDPubBibliography(obj): + return object_properties.ROLE_BIBLIOGRAPHY + if self._script.utilities.isDPubChapter(obj): + return object_properties.ROLE_CHAPTER + if self._script.utilities.isDPubConclusion(obj): + return object_properties.ROLE_CONCLUSION + if self._script.utilities.isDPubCredits(obj): + return object_properties.ROLE_CREDITS + if self._script.utilities.isDPubEndnotes(obj): + return object_properties.ROLE_ENDNOTES + if self._script.utilities.isDPubEpilogue(obj): + return object_properties.ROLE_EPILOGUE + if self._script.utilities.isDPubErrata(obj): + return object_properties.ROLE_ERRATA + if self._script.utilities.isDPubForeword(obj): + return object_properties.ROLE_FOREWORD + if self._script.utilities.isDPubGlossary(obj): + return object_properties.ROLE_GLOSSARY + if self._script.utilities.isDPubIndex(obj): + return object_properties.ROLE_INDEX + if self._script.utilities.isDPubIntroduction(obj): + return object_properties.ROLE_INTRODUCTION + if self._script.utilities.isDPubPagelist(obj): + return object_properties.ROLE_PAGELIST + if self._script.utilities.isDPubPart(obj): + return object_properties.ROLE_PART + if self._script.utilities.isDPubPreface(obj): + return object_properties.ROLE_PREFACE + if self._script.utilities.isDPubPrologue(obj): + return object_properties.ROLE_PROLOGUE + if self._script.utilities.isDPubToc(obj): + return object_properties.ROLE_TOC + elif role == "ROLE_DPUB_SECTION": + if self._script.utilities.isDPubAbstract(obj): + return object_properties.ROLE_ABSTRACT + if self._script.utilities.isDPubColophon(obj): + return object_properties.ROLE_COLOPHON + if self._script.utilities.isDPubCredit(obj): + return object_properties.ROLE_CREDIT + if self._script.utilities.isDPubDedication(obj): + return object_properties.ROLE_DEDICATION + if self._script.utilities.isDPubEpigraph(obj): + return object_properties.ROLE_EPIGRAPH + if self._script.utilities.isDPubExample(obj): + return object_properties.ROLE_EXAMPLE + if self._script.utilities.isDPubPullquote(obj): + return object_properties.ROLE_PULLQUOTE + if self._script.utilities.isDPubQna(obj): + return object_properties.ROLE_QNA + elif role == Atspi.Role.LIST_ITEM: + if self._script.utilities.isDPubBiblioentry(obj): + return object_properties.ROLE_BIBLIOENTRY + if self._script.utilities.isDPubEndnote(obj): + return object_properties.ROLE_ENDNOTE + else: + if self._script.utilities.isDPubCover(obj): + return object_properties.ROLE_COVER + if self._script.utilities.isDPubPagebreak(obj): + return object_properties.ROLE_PAGEBREAK + if self._script.utilities.isDPubSubtitle(obj): + return object_properties.ROLE_SUBTITLE + + if self._script.utilities.isLandmark(obj): + if self._script.utilities.isLandmarkWithoutType(obj): + return '' + if self._script.utilities.isLandmarkBanner(obj): + return object_properties.ROLE_LANDMARK_BANNER + if self._script.utilities.isLandmarkComplementary(obj): + return object_properties.ROLE_LANDMARK_COMPLEMENTARY + if self._script.utilities.isLandmarkContentInfo(obj): + return object_properties.ROLE_LANDMARK_CONTENTINFO + if self._script.utilities.isLandmarkMain(obj): + return object_properties.ROLE_LANDMARK_MAIN + if self._script.utilities.isLandmarkNavigation(obj): + return object_properties.ROLE_LANDMARK_NAVIGATION + if self._script.utilities.isLandmarkRegion(obj): + return object_properties.ROLE_LANDMARK_REGION + if self._script.utilities.isLandmarkSearch(obj): + return object_properties.ROLE_LANDMARK_SEARCH + if self._script.utilities.isLandmarkForm(obj): + role = Atspi.Role.FORM + elif self._script.utilities.isComment(obj): + role = Atspi.Role.COMMENT + + if not isinstance(role, Atspi.Role): + try: + return obj.getLocalizedRoleName() + except Exception: + return '' + + nonlocalized = Atspi.role_get_name(role) + atkRole = Atk.role_for_name(nonlocalized) + if atkRole == Atk.Role.INVALID and role == Atspi.Role.STATUS_BAR: + atkRole = Atk.role_for_name("statusbar") + + return Atk.role_get_localized_name(atkRole) + + def getStateIndicator(self, obj, **args): + if self._script.utilities.isSwitch(obj): + return self._generateSwitchState(obj, **args) + + role = args.get('role', AXObject.get_role(obj)) + + if role == Atspi.Role.MENU_ITEM: + return self._generateMenuItemCheckedState(obj, **args) + + if role in [Atspi.Role.RADIO_BUTTON, Atspi.Role.RADIO_MENU_ITEM]: + return self._generateRadioState(obj, **args) + + if role in [Atspi.Role.CHECK_BOX, Atspi.Role.CHECK_MENU_ITEM]: + return self._generateCheckedState(obj, **args) + + if role == Atspi.Role.TOGGLE_BUTTON: + return self._generateToggleState(obj, **args) + + if role == Atspi.Role.TABLE_CELL: + return self._generateCellCheckedState(obj, **args) + + return [] + + def getValue(self, obj, **args): + role = args.get('role', AXObject.get_role(obj)) + + if role == Atspi.Role.PROGRESS_BAR: + return self._generateProgressBarValue(obj, **args) + + if role in [Atspi.Role.SCROLL_BAR, Atspi.Role.SLIDER]: + return self._generatePercentage(obj, **args) + + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/guilabels.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/guilabels.py new file mode 100644 index 0000000..7cefc9d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/guilabels.py @@ -0,0 +1,944 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Labels for Cthulhu's GUIs. These have been put in their own module so that we +can present them in the correct language when users change the language on the +fly without having to reload a bunch of modules.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team" +__license__ = "LGPL" + +from .cthulhu_i18n import _, C_, ngettext + +# Translators: This string appears on a button in a dialog. "Activating" the +# selected item will perform the action that one would expect to occur if the +# object were clicked on with the mouse. If the object is a link, activating +# it will bring you to a new page. If the object is a button, activating it +# will press the button. If the object is a combobox, activating it will expand +# it to show all of its contents. And so on. +ACTIVATE = _("_Activate") + +# Translators: Cthulhu has a number of commands that override the default behavior +# within an application. For instance, on a web page Cthulhu's Structural Navigation +# command "h" moves you to the next heading. What should happen when you press +# "h" in an entry on a web page depends: If you want to resume reading content, +# "h" should move to the next heading; if you want to enter text, "h" should not +# move you to the next heading. Because Cthulhu doesn't know what you want to do, +# it has two modes: In browse mode, Cthulhu treats key presses as commands to read +# the content; in focus mode, Cthulhu treats key presses as something that should be +# handled by the focused widget. Cthulhu optionally can attempt to detect which mode +# is appropriate for the current situation and switch automatically. This string +# is a label for a GUI option to enable such automatic switching when structural +# navigation commands are used. As an example, if this setting were enabled, +# pressing "e" to move to the next entry would move focus there and also turn +# focus mode on so that the next press of "e" would type an "e" into the entry. +# If this setting is not enabled, the second press of "e" would continue to be +# a navigation command to move amongst entries. +AUTO_FOCUS_MODE_STRUCT_NAV = _("Automatic focus mode during structural navigation") + +# Translators: Cthulhu has a number of commands that override the default behavior +# within an application. For instance, if you are at the bottom of an entry and +# press Down arrow, should you leave the entry? It depends on if you want to +# resume reading content or if you are editing the text in the entry. Because +# Cthulhu doesn't know what you want to do, it has two modes: In browse mode, Cthulhu +# treats key presses as commands to read the content; in focus mode, Cthulhu treats +# key presses as something that should be handled by the focused widget. Cthulhu +# optionally can attempt to detect which mode is appropriate for the current +# situation and switch automatically. This string is a label for a GUI option to +# enable such automatic switching when caret navigation commands are used. As an +# example, if this setting were enabled, pressing Down Arrow would allow you to +# move into an entry but once you had done so, Cthulhu would switch to Focus mode +# and subsequent presses of Down Arrow would be controlled by the web browser +# and not by Cthulhu. If this setting is not enabled, Cthulhu would continue to control +# what happens when you press an arrow key, thus making it possible to arrow out +# of the entry. +AUTO_FOCUS_MODE_CARET_NAV = _("Automatic focus mode during caret navigation") + +# Translators: Cthulhu has a number of commands that override the default behavior +# within an application. For instance, if you are at the bottom of an entry and +# press Down arrow, should you leave the entry? It depends on if you want to +# resume reading content or if you are editing the text in the entry. Because +# Cthulhu doesn't know what you want to do, it has two modes: In browse mode, Cthulhu +# treats key presses as commands to read the content; in focus mode, Cthulhu treats +# key presses as something that should be handled by the focused widget. Cthulhu +# optionally can attempt to detect which mode is appropriate for the current +# situation and switch automatically. This string is a label for a GUI option to +# enable such automatic switching when native navigation commands are used. +# Here "native" means "not Cthulhu"; it could be a browser navigation command such +# as the Tab key, or it might be a web page behavior, such as the search field +# automatically gaining focus when the page loads. +AUTO_FOCUS_MODE_NATIVE_NAV = _("Automatic focus mode during native navigation") + +# Translators: A single braille cell on a refreshable braille display consists +# of 8 dots. Dot 7 is the dot in the bottom left corner. If the user selects +# this option, Dot 7 will be used to 'underline' text of interest, e.g. when +# "marking"/indicating that a given word is bold. +BRAILLE_DOT_7 = _("Dot _7") + +# Translators: A single braille cell on a refreshable braille display consists +# of 8 dots. Dot 8 is the dot in the bottom right corner. If the user selects +# this option, Dot 8 will be used to 'underline' text of interest, e.g. when +# "marking"/indicating that a given word is bold. +BRAILLE_DOT_8 = _("Dot _8") + +# Translators: A single braille cell on a refreshable braille display consists +# of 8 dots. Dots 7-8 are the dots at the bottom. If the user selects this +# option, Dots 7-8 will be used to 'underline' text of interest, e.g. when +# "marking"/indicating that a given word is bold. +BRAILLE_DOT_7_8 = _("Dots 7 an_d 8") + +# Translators: This is the label for a button in a dialog. +BTN_CANCEL = _("_Cancel") + +# Translators: This is the label for a button in a dialog. +BTN_JUMP_TO = _("_Jump to") + +# Translators: This is the label for a button in a dialog. +BTN_OK = _("_OK") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter (which Speech Dispatcher refers to as 'spell'), +# or play a tone (which Speech Dispatcher refers to as a sound 'icon'.) This +# string to be translated appears as a combo box item in Cthulhu's Preferences. +CAPITALIZATION_STYLE_ICON = C_("capitalization style", "Icon") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter (which Speech Dispatcher refers to as 'spell'), +# or play a tone (which Speech Dispatcher refers to as a sound 'icon'.) This +# string to be translated appears as a combo box item in Cthulhu's Preferences. +CAPITALIZATION_STYLE_NONE = C_("capitalization style", "None") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter (which Speech Dispatcher refers to as 'spell'), +# or play a tone (which Speech Dispatcher refers to as a sound 'icon'.) This +# string to be translated appears as a combo box item in Cthulhu's Preferences. +CAPITALIZATION_STYLE_SPELL = C_("capitalization style", "Spell") + +# Translators: If this checkbox is checked, then Cthulhu will tell you when one of +# your buddies is typing a message. +CHAT_ANNOUNCE_BUDDY_TYPING = _("Announce when your _buddies are typing") + +# Translators: If this checkbox is checked, then Cthulhu will provide the user with +# chat room specific message histories rather than just a single history which +# contains the latest messages from all the chat rooms that they are in. +CHAT_SEPARATE_MESSAGE_HISTORIES = _("Provide chat room specific _message histories") + +# Translators: This is the label of a panel holding options for how messages in +# this application's chat rooms should be spoken. The options are: Speak messages +# from all channels (i.e. even if the chat application doesn't have focus); speak +# messages from a channel only if it is the active channel; speak messages from +# any channel, but only if the chat application has focus. +CHAT_SPEAK_MESSAGES_FROM = _("Speak messages from") + +# Translators: This is the label of a radio button. If it is selected, Cthulhu will +# speak all new chat messages as they appear irrespective of whether or not the +# chat application currently has focus. This is the default behaviour. +CHAT_SPEAK_MESSAGES_ALL = _("All cha_nnels") + +# Translators: This is the label of a radio button. If it is selected, Cthulhu will +# speak all new chat messages as they appear if and only if the chat application +# has focus. The string substitution is for the application name (e.g Pidgin). +CHAT_SPEAK_MESSAGES_ALL_IF_FOCUSED = _("All channels when an_y %s window is active") + +# Translators: This is the label of a radio button. If it is selected, Cthulhu will +# only speak new chat messages for the currently active channel, irrespective of +# whether the chat application has focus. +CHAT_SPEAK_MESSAGES_ACTIVE = _("A channel only if its _window is active") + +# Translators: If this checkbox is checked, then Cthulhu will speak the name of the +# chat room prior to presenting an incoming message. +CHAT_SPEAK_ROOM_NAME = _("_Speak Chat Room name") + +# Translators: When presenting the content of a line on a web page, Cthulhu by +# default presents the full line, including any links or form fields on that +# line, in order to reflect the on-screen layout as seen by sighted users. +# Not all users like this presentation, however, and prefer to have objects +# treated as if they were on individual lines, such as is done by Windows +# screen readers, so that unrelated objects (e.g. links in a navbar) are not +# all jumbled together. As a result, this is now configurable. If layout mode +# is enabled, Cthulhu will present the full line as it appears on the screen; if +# it is disabled, Cthulhu will treat each object as if it were on a separate line, +# both for presentation and navigation. +CONTENT_LAYOUT_MODE = _("Enable layout mode for content") + +# Translators: Cthulhu's keybindings support double and triple "clicks" or key +# presses, similar to using a mouse. This string appears in Cthulhu's preferences +# dialog after a keybinding which requires a double click. +CLICK_COUNT_DOUBLE = _("double click") + +# Translators: Cthulhu's keybindings support double and triple "clicks" or key +# presses, similar to using a mouse. This string appears in Cthulhu's preferences +# dialog after a keybinding which requires a triple click. +CLICK_COUNT_TRIPLE = _("triple click") + +# Translators: This is a label which will appear in the list of available speech +# engines as a special item. It refers to the default engine configured within +# the speech subsystem. Apart from this item, the user will have a chance to +# select a particular speech engine by its real name (Festival, IBMTTS, etc.) +DEFAULT_SYNTHESIZER = _("Default Synthesizer") + +# Translators: This is a label for a column header in Cthulhu's pronunciation +# dictionary. The pronunciation dictionary allows the user to correct words +# which the speech synthesizer mispronounces (e.g. a person's name, a technical +# word) or doesn't pronounce as the user desires (e.g. an acronym) by providing +# an alternative string. The "Actual String" here refers to the word to be +# corrected as it would actually appear in text being read. Example: "LOL". +DICTIONARY_ACTUAL_STRING = _("Actual String") + +# Translators: This is a label for a column header in Cthulhu's pronunciation +# dictionary. The pronunciation dictionary allows the user to correct words +# which the speech synthesizer mispronounces (e.g. a person's name, a technical +# word) or doesn't pronounce as the user desires (e.g. an acronym) by providing +# an alternative string. The "Replacement String" here refers to how the user +# would like the "Actual String" to be pronounced by the speech synthesizer. +# Example: "L O L" or "Laughing Out Loud" (for Actual String "LOL"). +DICTIONARY_REPLACEMENT_STRING = _("Replacement String") + +# Translators: Cthulhu has an "echo" feature to present text as it is being written +# by the user. While Cthulhu's "key echo" options present the actual keyboard keys +# being pressed, "character echo" presents the character/string of length 1 that +# is inserted as a result of the keypress. +ECHO_CHARACTER = _("Enable echo by cha_racter") + +# Translators: Cthulhu has an "echo" feature to present text as it is being written +# by the user. This string refers to a "key echo" option. When this option is +# enabled, dead keys will be announced when pressed. +ECHO_DIACRITICAL = _("Enable non-spacing _diacritical keys") + +# Translators: Cthulhu has a "find" feature which allows the user to search the +# active application for on screen text and widgets. This label is associated +# with the setting to begin the search from the current location rather than +# from the top of the screen. +FIND_START_AT_CURRENT_LOCATION = _("C_urrent location") + +# Translators: This is the label for a spinbutton. This option allows the user +# to specify the number of matched characters that must be present before Cthulhu +# speaks the line that contains the results from an application's Find toolbar. +FIND_MINIMUM_MATCH_LENGTH = _("Minimum length of matched text:") + +# Translators: This is the label of a panel containing options for what Cthulhu +# presents when the user is in the Find toolbar of an application, e.g. Firefox. +FIND_OPTIONS = _("Find Options") + +# Translators: This is the label for a checkbox. This option controls whether +# the line that contains the match from an application's Find toolbar should +# always be spoken, or only spoken if it is a different line than the line +# which contained the last match. +FIND_ONLY_SPEAK_CHANGED_LINES = _("Onl_y speak changed lines during find") + +# Translators: This is the label for a checkbox. This option controls whether or +# not Cthulhu will automatically speak the line that contains the match while the +# user is performing a search from the Find toolbar of an application, e.g. +# Firefox. +FIND_SPEAK_RESULTS = _("Speak results during _find") + +# Translators: Command is a table column header where the cells in the column +# are a sentence that briefly describes what action Cthulhu will take if and when +# the user invokes that keyboard command. +KB_HEADER_FUNCTION = _("Command") + +# Translators: Key Binding is a table column header where the cells in the +# column represent keyboard combinations the user can press to invoke Cthulhu +# commands. +KB_HEADER_KEY_BINDING = _("Key Binding") + +# Translators: This string is a label for the group of Cthulhu commands which +# can be used in any setting, task, or application. They are not specific +# to, for instance, web browsing. +KB_GROUP_DEFAULT = C_("keybindings", "Default") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to its "learn mode". Please use the same translation as done +# in cmdnames.py +KB_GROUP_LEARN_MODE = C_("keybindings", "Learn mode") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to presenting and performing the accessible actions associated +# with the current object. +KB_GROUP_ACTIONS = _("Actions") + +# Translators: An external braille device has buttons on it that permit the +# user to create input gestures from the braille device. The braille bindings +# are what determine the actions Cthulhu will take when the user presses these +# buttons. +KB_GROUP_BRAILLE = _("Braille Bindings") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to saving and jumping among objects via "bookmarks". +KB_GROUP_BOOKMARKS = _("Bookmarks") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to presenting the date and time. +KB_GROUP_DATE_AND_TIME = _("Date and time") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to presenting the object under the mouse pointer in speech +# and/or braille. The translation should be consistent with the string +# used in cmdnames.py. +KB_GROUP_MOUSE_REVIEW = _("Mouse review") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to object navigation. +KB_GROUP_OBJECT_NAVIGATION = _("Object navigation") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to presenting information about the current location, such as +# the title, status bar, and default button of the current window; the +# name, role, and location of the currently-focused object; the selected +# text in the currently-focused object; etc. +KB_GROUP_WHERE_AM_I = _("Object details") + +# Translators: This string is a label for the group of Cthulhu commands which +# do not currently have an associated key binding. +KB_GROUP_UNBOUND = _("Unbound") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to Cthulhu's "flat review" feature. This feature allows the blind +# user to explore the text in a window in a 2D fashion. That is, Cthulhu treats +# all the text from all objects in a window (e.g., buttons, labels, etc.) as +# a sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Those commands are all listed under this group label. +KB_GROUP_FLAT_REVIEW = _("Flat review") + +# Translators: This string is a label for the group of Cthulhu commands which +# are related to Cthulhu's speech and verbosity settings. This group of commands +# allows on-the-fly configuration of how much (or little) Cthulhu says about a +# particular object, as well certain aspects of the voice with which things +# are spoken. +KB_GROUP_SPEECH_VERBOSITY = _("Speech and verbosity") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. The flat review feature allows +# the user to explore this text by the {previous,next} {line,word,character}. +# Normally the contents are navigated without leaving the application being +# reviewed. There is a command which will place the entire contents of the +# flat review representation into a text view to make it easy to review +# and copy the text. This string is the title of the window with the text view. +FLAT_REVIEW_CONTENTS = _("Flat review contents") + +# Translators: Modified is a table column header in Cthulhu's preferences dialog. +# This column contains a checkbox which indicates whether a key binding +# for an Cthulhu command has been changed by the user to something other than its +# default value. +KB_MODIFIED = C_("keybindings", "Modified") + +# Translators: This label refers to the keyboard layout (desktop or laptop). +KEYBOARD_LAYOUT_DESKTOP = _("_Desktop") + +# Translators: Cthulhu has a feature to list all of the notification messages +# received, similar to the functionality gnome-shell provides when you press +# Super+M, but it works in all desktop environments. Cthulhu's list is a table +# with two columns, one column for the text of the notification and one +# column for the time of the notification. This string is a column header +# for the text of the notifications. +NOTIFICATIONS_COLUMN_HEADER = C_("notification presenter", "Notifications") + +# Translators: Cthulhu has a feature to list all of the notification messages +# received, similar to the functionality gnome-shell provides when you press +# Super+M, but it works in all desktop environments. Cthulhu's list is a table +# with two columns, one column for the text of the notification and one +# column for the time of the notification. This string is a column header +# for the time, which will be relative (e.g. "10 minutes ago") or absolute. +NOTIFICATIONS_RECEIVED_TIME = C_("notification presenter", "Received") + +# Translators: This string is a label for the group of Cthulhu commands which +# are associated with presenting notifications. +KB_GROUP_NOTIFICATIONS = _("Notification presenter") + +# Translators: Cthulhu's preferences can be configured on a per-application basis, +# allowing users to customize Cthulhu's behavior, keybindings, etc. to work one +# way in LibreOffice and another way in a chat application. This string is the +# title of Cthulhu's application-specific preferences dialog for an application. +# The string substituted in is the accessible name of the application (e.g. +# "Gedit", "Firefox", etc. +PREFERENCES_APPLICATION_TITLE = _("Cthulhu Preferences for %s") + +# Translators: This is a table column header. This column consists of a single +# checkbox. If the checkbox is checked, Cthulhu will indicate the associated item +# or attribute by "marking" it in braille. "Marking" is not the same as writing +# out the word; instead marking refers to adding some other indicator, e.g. +# "underlining" with braille dots 7-8 a word that is bold. +PRESENTATION_MARK_IN_BRAILLE = _("Mark in braille") + +# Translators: "Present Unless" is a column header of the text attributes panel +# of the Cthulhu preferences dialog. On this panel, the user can select a set of +# text attributes that they would like spoken and/or indicated in braille. +# Because the list of attributes could get quite lengthy, we provide the option +# to always speak/braille a text attribute *unless* its value is equal to the +# value given by the user in this column of the list. For example, given the +# text attribute "underline" and a present unless value of "none", the user is +# stating that he/she would like to have underlined text announced for all cases +# (single, double, low, etc.) except when the value of underline is none (i.e. +# when it's not underlined). "Present" here is being used as a verb. +PRESENTATION_PRESENT_UNLESS = _("Present Unless") + +# Translators: This is a table column header. The "Speak" column consists of a +# single checkbox. If the checkbox is checked, Cthulhu will speak the associated +# item or attribute (e.g. saying "Bold" as part of the information presented +# when the user gives the Cthulhu command to obtain the format and font details of +# the current text). +PRESENTATION_SPEAK = _("Speak") + +# Translators: This is the title of a message dialog informing the user that +# he/she attempted to save a new user profile under a name which already exists. +# A "user profile" is a collection of settings which apply to a given task, such +# as a "Spanish" profile which would use Spanish text-to-speech and Spanish +# braille and selected when reading Spanish content. +PROFILE_CONFLICT_TITLE = _("Save Profile As Conflict") + +# Translators: This is the label of a message dialog informing the user that +# he/she attempted to save a new user profile under a name which already exists. +# A "user profile" is a collection of settings which apply to a given task, such +# as a "Spanish" profile which would use Spanish text-to-speech and Spanish +# braille and selected when reading Spanish content. +PROFILE_CONFLICT_LABEL = _("User Profile Conflict!") + +# Translators: This is the message in a dialog informing the user that he/she +# attempted to save a new user profile under a name which already exists. +# A "user profile" is a collection of settings which apply to a given task, such +# as a "Spanish" profile which would use Spanish text-to-speech and Spanish +# braille and selected when reading Spanish content. +PROFILE_CONFLICT_MESSAGE = _("Profile %s already exists.\n" \ + "Continue updating the existing profile with " \ + "these new changes?") + +# Translators: This text is displayed in a message dialog when a user indicates +# he/she wants to switch to a new user profile which will cause him/her to lose +# settings which have been altered but not yet saved. A "user profile" is a +# collection of settings which apply to a given task such as a "Spanish" profile +# which would use Spanish text-to-speech and Spanish braille and selected when +# reading Spanish content. +PROFILE_LOAD_LABEL = _("Load user profile") + +# Translators: This text is displayed in a message dialog when a user indicates +# he/she wants to switch to a new user profile which will cause him/her to lose +# settings which have been altered but not yet saved. A "user profile" is a +# collection of settings which apply to a given task such as a "Spanish" profile +# which would use Spanish text-to-speech and Spanish braille and selected when +# reading Spanish content. +PROFILE_LOAD_MESSAGE = \ + _("You are about to change the active profile. If you\n" \ + "have just made changes in your preferences, they will\n" \ + "be dropped at profile load.\n\n" \ + "Continue loading profile discarding previous changes?") + +# Translators: Profiles in Cthulhu make it possible for users to quickly switch +# amongst a group of pre-defined settings (e.g. an 'English' profile for reading +# text written in English using an English-language speech synthesizer and +# braille rules, and a similar 'Spanish' profile for reading Spanish text. The +# following string is the title of a dialog in which users can save a newly- +# defined profile. +PROFILE_SAVE_AS_TITLE = _("Save Profile As") + +# Translators: Profiles in Cthulhu make it possible for users to quickly switch +# amongst a group of pre-defined settings (e.g. an 'English' profile for reading +# text written in English using an English-language speech synthesizer and +# braille rules, and a similar 'Spanish' profile for reading Spanish text. The +# following string is the label for a text entry in which the user enters the +# name of a new settings profile being saved via the 'Save Profile As' dialog. +PROFILE_NAME_LABEL = _("_Profile Name:") + +# Translators: Profiles in Cthulhu make it possible for users to quickly switch +# amongst a group of pre-defined settings (e.g. an 'English' profile for reading +# text written in English using an English-language speech synthesizer and +# braille rules, and a similar 'Spanish' profile for reading Spanish text. +# The following is a label in a dialog informing the user that he/she +# is about to remove a user profile, and action that cannot be undone. +PROFILE_REMOVE_LABEL = _("Remove user profile") + +# Translators: Profiles in Cthulhu make it possible for users to quickly switch +# amongst a group of pre-defined settings (e.g. an 'English' profile for reading +# text written in English using an English-language speech synthesizer and +# braille rules, and a similar 'Spanish' profile for reading Spanish text. +# The following is a message in a dialog informing the user that he/she +# is about to remove a user profile, an action that cannot be undone. +PROFILE_REMOVE_MESSAGE = _("You are about to remove profile %s. " \ + "All unsaved settings and settings saved in this " \ + "profile will be lost. Do you want to continue " \ + "and remove this profile and all related settings?") + +# Translators: Cthulhu has a setting which determines which progress bar updates +# should be announced. Choosing "All" means that Cthulhu will present progress bar +# updates regardless of what application and window they happen to be in. +PROGRESS_BAR_ALL = C_("ProgressBar", "All") + +# Translators: Cthulhu has a setting which determines which progress bar updates +# should be announced. Choosing "Application" means that Cthulhu will present +# progress bar updates as long as the progress bar is in the active application +# (but not necessarily in the current window). +PROGRESS_BAR_APPLICATION = C_("ProgressBar", "Application") + +# Translators: Cthulhu has a setting which determines which progress bar updates +# should be announced. Choosing "Window" means that Cthulhu will present progress +# bar updates as long as the progress bar is in the active window. +PROGRESS_BAR_WINDOW = C_("ProgressBar", "Window") + +# Translators: If this setting is chosen, no punctuation symbols will be spoken +# as a user reads a document. +PUNCTUATION_STYLE_NONE = C_("punctuation level", "_None") + +# Translators: If this setting is chosen, common punctuation symbols (like +# comma, period, question mark) will not be spoken as a user reads a document, +# but less common symbols (such as #, @, $) will. +PUNCTUATION_STYLE_SOME = _("So_me") + +# Translators: If this setting is chosen, the majority of punctuation symbols +# will be spoken as a user reads a document. +PUNCTUATION_STYLE_MOST = _("M_ost") + +# Translators: If this setting is chosen and the user is reading over an entire +# document, Cthulhu will pause at the end of each line. +SAY_ALL_STYLE_LINE = _("Line") + +# Translators: If this setting is chosen and the user is reading over an entire +# document, Cthulhu will pause at the end of each sentence. +SAY_ALL_STYLE_SENTENCE = _("Sentence") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a blockquote. +SN_HEADER_BLOCKQUOTE = C_("structural navigation", "Blockquote") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a button. +SN_HEADER_BUTTON = C_("structural navigation", "Button") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the caption of a table. +SN_HEADER_CAPTION = C_("structural navigation", "Caption") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the label of a check box. +SN_HEADER_CHECK_BOX = C_("structural navigation", "Check Box") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text displayed for a web element with an "onClick" handler. +SN_HEADER_CLICKABLE = C_("structural navigation", "Clickable") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the selected item in a combo box. +SN_HEADER_COMBO_BOX = C_("structural navigation", "Combo Box") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the description of an element. +SN_HEADER_DESCRIPTION = C_("structural navigation", "Description") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a heading. +SN_HEADER_HEADING = C_("structural navigation", "Heading") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the title associated with an iframe. +SN_HEADER_IFRAME = C_("structural navigation", "Internal Frame") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text (alt text, title, etc.) associated with an image. +SN_HEADER_IMAGE = C_("structural navigation", "Image") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the label of a form field. +SN_HEADER_LABEL = C_("structural navigation", "Label") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a landmark. ARIA role landmarks are the W3C defined HTML +# tag attribute 'role' used to identify important part of webpage like banners, +# main context, search etc. +SN_HEADER_LANDMARK = C_("structural navigation", "Landmark") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of a column which +# contains the level of a heading. Level will be a "1" for

, a "2" for

, +# and so on. +SN_HEADER_LEVEL = C_("structural navigation", "Level") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a link. +SN_HEADER_LINK = C_("structural navigation", "Link") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a list. +SN_HEADER_LIST = C_("structural navigation", "List") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a list item. +SN_HEADER_LIST_ITEM = C_("structural navigation", "List Item") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of an object. +SN_HEADER_OBJECT = C_("structural navigation", "Object") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of a paragraph. +SN_HEADER_PARAGRAPH = C_("structural navigation", "Paragraph") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the label of a radio button. +SN_HEADER_RADIO_BUTTON = C_("structural navigation", "Radio Button") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the role of a widget. Examples include "heading", "paragraph", +# "table", "combo box", etc. +SN_HEADER_ROLE = C_("structural navigation", "Role") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the selected item of a form field. +SN_HEADER_SELECTED_ITEM = C_("structural navigation", "Selected Item") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the state of a widget. Examples include "checked"/"not checked", +# "selected"/"not selected", "visited/not visited", etc. +SN_HEADER_STATE = C_("structural navigation", "State") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the text of an entry. +SN_HEADER_TEXT = C_("structural navigation", "Text") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the URI of a link. +SN_HEADER_URI = C_("structural navigation", "URI") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title for a column which +# contains the value of a form field. +SN_HEADER_VALUE = C_("structural navigation", "Value") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_BLOCKQUOTE = C_("structural navigation", "Blockquotes") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_BUTTON = C_("structural navigation", "Buttons") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_CHECK_BOX = C_("structural navigation", "Check Boxes") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +# "Clickables" are web elements which have an "onClick" handler. +SN_TITLE_CLICKABLE = C_("structural navigation", "Clickables") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_COMBO_BOX = C_("structural navigation", "Combo Boxes") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_ENTRY = C_("structural navigation", "Entries") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_FORM_FIELD = C_("structural navigation", "Form Fields") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_HEADING = C_("structural navigation", "Headings") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_IFRAME = C_("structural navigation", "Internal Frames") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_IMAGE = C_("structural navigation", "Images") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +# Level will be a "1" for

, a "2" for

, and so on. +SN_TITLE_HEADING_AT_LEVEL = C_("structural navigation", "Headings at Level %d") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +# ARIA role landmarks are the W3C defined HTML tag attribute 'role' used to +# identify important part of webpage like banners, main context, search etc. +SN_TITLE_LANDMARK = C_("structural navigation", "Landmarks") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +# A 'large object' is a logical chunk of text, such as a paragraph, a list, +# a table, etc. +SN_TITLE_LARGE_OBJECT = C_("structural navigation", "Large Objects") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_LINK = C_("structural navigation", "Links") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_LIST = C_("structural navigation", "Lists") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_LIST_ITEM = C_("structural navigation", "List Items") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_PARAGRAPH = C_("structural navigation", "Paragraphs") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_RADIO_BUTTON = C_("structural navigation", "Radio Buttons") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_TABLE = C_("structural navigation", "Tables") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_UNVISITED_LINK = C_("structural navigation", "Unvisited Links") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is the title of such a dialog box. +SN_TITLE_VISITED_LINK = C_("structural navigation", "Visited Links") + +# Translators: This is the title of a panel holding options for how to navigate +# HTML content (e.g., Cthulhu caret navigation, positioning of caret, structural +# navigation, etc.). +PAGE_NAVIGATION = _("Page Navigation") + +# Translators: When the user loads a new web page, they can optionally have Cthulhu +# automatically start reading the page from beginning to end. This is the label +# of a checkbox in which users can indicate their preference. +READ_PAGE_UPON_LOAD = \ + _("Automatically start speaking a page when it is first _loaded") + +# Translators: When the user loads a new web page, they can optionally have Cthulhu +# automatically summarize details about the page, such as the number of elements +# (landmarks, forms, links, tables, etc.). +PAGE_SUMMARY_UPON_LOAD = _("_Present summary of a page when it is first loaded") + +# Translators: Different speech systems and speech engines work differently when +# it comes to handling pauses (e.g. sentence boundaries). This property allows +# the user to specify whether speech should be sent to the speech synthesis +# system immediately when a pause directive is encountered or if it should be +# queued up and sent to the speech synthesis system once the entire set of +# utterances has been calculated. +SPEECH_BREAK_INTO_CHUNKS = _("Break speech into ch_unks between pauses") + +# Translators: This string will appear in the list of available voices for the +# current speech engine. "%s" will be replaced by the name of the current speech +# engine, such as "Festival default voice" or "IBMTTS default voice". It refers +# to the default voice configured for given speech engine within the speech +# subsystem. Apart from this item, the list will contain the names of all +# available "real" voices provided by the speech engine. +SPEECH_DEFAULT_VOICE = _("%s default voice") + +# Translators: This refers to the voice used by Cthulhu when presenting the content +# of the screen and other messages. +SPEECH_VOICE_TYPE_DEFAULT = C_("VoiceType", "Default") + +# Translators: This refers to the voice used by Cthulhu when presenting one or more +# characters which is part of a hyperlink. +SPEECH_VOICE_TYPE_HYPERLINK = C_("VoiceType", "Hyperlink") + +# Translators: This refers to the voice used by Cthulhu when presenting information +# which is not displayed on the screen as text, but is still being communicated +# by the system in some visual fashion. For instance, Cthulhu says "misspelled" to +# indicate the presence of the red squiggly line found under a spelling error; +# Cthulhu might say "3 of 6" when a user Tabs into a list of six items and the +# third item is selected. And so on. +SPEECH_VOICE_TYPE_SYSTEM = C_("VoiceType", "System") + +# Translators: This refers to the voice used by Cthulhu when presenting one or more +# characters which is written in uppercase. +SPEECH_VOICE_TYPE_UPPERCASE = C_("VoiceType", "Uppercase") + +# Translators this label refers to the name of particular speech synthesis +# system. (http://devel.freebsoft.org/speechd) +SPEECH_DISPATCHER = _("Speech Dispatcher") + +# Translators: This is a label for a group of options related to Cthulhu's behavior +# when presenting an application's spell check dialog. +SPELL_CHECK = C_("OptionGroup", "Spell Check") + +# Translators: This is a label for a checkbox associated with an Cthulhu setting. +# When this option is enabled, Cthulhu will spell out the current error in addition +# to speaking it. For example, if the misspelled word is "foo," enabling this +# setting would cause Cthulhu to speak "f o o" after speaking "foo". +SPELL_CHECK_SPELL_ERROR = _("Spell _error") + +# Translators: This is a label for a checkbox associated with an Cthulhu setting. +# When this option is enabled, Cthulhu will spell out the current suggestion in +# addition to speaking it. For example, if the misspelled word is "foo," and +# the first suggestion is "for" enabling this setting would cause Cthulhu to speak +# "f o r" after speaking "for". +SPELL_CHECK_SPELL_SUGGESTION = _("Spell _suggestion") + +# Translators: This is a label for a checkbox associated with an Cthulhu setting. +# When this option is enabled, Cthulhu will present the context (surrounding text, +# typically the sentence or line) in which the mistake occurred. +SPELL_CHECK_PRESENT_CONTEXT = _("Present _context of error") + +# Translators: This is a label for an option to tell Cthulhu whether or not it +# should speak the coordinates of the current spreadsheet cell. Coordinates are +# the row and column position within the spreadsheet (i.e. A1, B1, C2 ...) +SPREADSHEET_SPEAK_CELL_COORDINATES = _("Speak spreadsheet cell coordinates") + +# Translators: This is a label for an option which controls what Cthulhu speaks when +# presenting selection changes in a spreadsheet. By default, Cthulhu will speak just +# what changed. For instance, if cells A1 through A8 are already selected, and the +# user adds A9 to the selection, Cthulhu by default would just say "A9 selected." +# Some users, however, prefer to have Cthulhu always announce the entire selected range, +# i.e. in the same scenario say "A1 through A9 selected." Those users should enable +# this option. +SPREADSHEET_SPEAK_SELECTED_RANGE = _("Always speak selected spreadsheet range") + +# Translators: This is a label for an option for whether or not to speak the +# header of a table cell in document content. +TABLE_ANNOUNCE_CELL_HEADER = _("Announce cell _header") + +# Translators: This is the title of a panel containing options for specifying +# how to navigate tables in document content. +TABLE_NAVIGATION = _("Table Navigation") + +# Translators: This is a label for an option to tell Cthulhu to skip over empty/ +# blank cells when navigating tables in document content. +TABLE_SKIP_BLANK_CELLS = _("Skip _blank cells") + +# Translators: When users are navigating a table, they sometimes want the entire +# row of a table read; other times they want just the current cell presented to +# them. This label is associated with the default presentation to be used. +TABLE_SPEAK_CELL = _("Speak _cell") + +# Translators: This is a label for an option to tell Cthulhu whether or not it +# should speak table cell coordinates in document content. +TABLE_SPEAK_CELL_COORDINATES = _("Speak _cell coordinates") + +# Translators: This is a label for an option to tell Cthulhu whether or not it +# should speak the span size of a table cell (e.g., how many rows and columns +# a particular table cell spans in a table). +TABLE_SPEAK_CELL_SPANS = _("Speak _multiple cell spans") + +# Translators: This is a table column header. "Attribute" here refers to text +# attributes such as bold, underline, family-name, etc. +TEXT_ATTRIBUTE_NAME = _("Attribute Name") + +# Translators: Gecko native caret navigation is where Firefox itself controls +# how the arrow keys move the caret around HTML content. It's often broken, so +# Cthulhu needs to provide its own support. As such, Cthulhu offers the user the +# ability to switch between the Firefox mode and the Cthulhu mode. This is the +# label of a checkbox in which users can indicate their default preference. +USE_CARET_NAVIGATION = _("Control caret navigation") + +# Translators: Cthulhu provides keystrokes to navigate HTML content in a structural +# manner: go to previous/next header, list item, table, etc. This is the label +# of a checkbox in which users can indicate their default preference. +USE_STRUCTURAL_NAVIGATION = _("Enable _structural navigation") + +# Translators: This refers to the amount of information Cthulhu provides about a +# particular object that receives focus. +VERBOSITY_LEVEL_BRIEF = _("Brie_f") + +def notifications_count(count): + """Returns the gui label representing the notifications count.""" + + # Translators: Cthulhu has a feature to list all of the notification messages + # received, similar to the functionality gnome-shell provides when you press + # Super+M, but it works in all desktop environments. This string is the title + # of the dialog that contains the list of notification messages. The string + # substitution is for the number of messages in the list. + return ngettext("%d notification", "%d notifications", count) % count diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/highlighter.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/highlighter.py new file mode 100644 index 0000000..cc6d581 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/highlighter.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for drawing highlights over an area of interest.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +from . import debug + +try: + import cairo + import gi + gi.require_version('Gtk', '3.0') + from gi.repository import Gtk + CAIRO_AVAILABLE = True +except Exception as error: + tokens = ["HIGHLIGHTER: GtkHighlighter unavailable:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + CAIRO_AVAILABLE = False + +class Highlighter: + """Base class of all highlighters supported by Cthulhu.""" + + HIGHLIGHT = "highlight" + RECTANGLE = "rectangle" + UNDERLINE = "underline" + + RED = (1, 0, 0) + BLUE = (0, 0, 1) + GREEN = (0, 1, 0) + YELLOW = (1, 1, 0) + PURPLE = (0.5, 0, 0.5) + ORANGE = (1, 0.5, 0) + PINK = (1, 0.75, 0.8) + CYAN = (0, 1, 1) + MAGENTA = (1, 0, 1) + LIME = (0.5, 1, 0) + NAVY = (0, 0, 0.5) + TEAL = (0, 0.5, 0.5) + BLACK = (0, 0, 0) + WHITE = (1, 1, 1) + + def __init__(self, highlight_type, color, alpha, thickness, padding, fill_color, fill_alpha): + self._highlight_type = highlight_type + self._color = color + self._alpha = alpha + self._thickness = thickness + self._padding = padding + self._fill_color = fill_color + self._fill_alpha = fill_alpha + self._gui = self._create_gui() + + def _create_gui(self): + """Creates the gui for the overlay.""" + return None + + def _draw_highlight(self, painter): + """Called by highlight to draw a highlight over the item.""" + pass + + def _draw_rectangle(self, painter): + """Called by highlight to draw a rectangle around the item.""" + pass + + def _draw_underline(self, painter): + """Called by highlight to draw an underline under the item.""" + pass + + def highlight(self, x, y, width, height): + """Draws the desired indicator over the specified box.""" + pass + + def quit(self): + """Quits the highlighter.""" + pass + + +class GtkHighlighter(Highlighter): + """Highlighter that uses a GtkWindow to highlight items.""" + + def __init__(self, + highlight_type=Highlighter.UNDERLINE, + color=Highlighter.GREEN, + alpha=1.0, + thickness=5, + padding=5, + fill_color=None, + fill_alpha=None): + if not CAIRO_AVAILABLE: + msg = "GTK HIGHLIGHTER: Unavailable. Is Cairo installed?" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().__init__(highlight_type, color, alpha, thickness, padding, fill_color, fill_alpha) + self._drawing_area = None + + def _create_gui(self): + """Creates the gui for the overlay.""" + + gui = Gtk.Window() + gui.set_decorated(False) + gui.set_accept_focus(False) + gui.set_app_paintable(True) + gui.set_skip_taskbar_hint(True) + gui.set_skip_pager_hint(True) + + screen = gui.get_screen() + visual = screen.get_rgba_visual() + if visual and screen.is_composited(): + gui.set_visual(visual) + + self._drawing_area = Gtk.DrawingArea() + self._drawing_area.connect("draw", self._on_draw) + gui.add(self._drawing_area) + return gui + + def _on_draw(self, widget, painter): + """Signal handler for the 'draw' event.""" + + if self._highlight_type == self.HIGHLIGHT: + self._draw_highlight(painter) + elif self._highlight_type == self.RECTANGLE: + self._draw_rectangle(painter) + elif self._highlight_type == self.UNDERLINE: + self._draw_underline(painter) + + def _draw_highlight(self, painter): + """Called by highlight to draw a highlight over the item.""" + + if self._fill_color is None: + self._fill_color = self.YELLOW + if self._fill_alpha is None: + self._fill_alpha = 0.3 + + fill = (*self._fill_color, self._fill_alpha) + painter.set_source_rgba(*fill) + painter.set_operator(cairo.OPERATOR_SOURCE) + painter.paint() + painter.set_operator(cairo.OPERATOR_OVER) + + def _draw_rectangle(self, painter): + """Called by highlight to draw a rectangle around the item.""" + + x = self._padding + y = self._padding + width = self._gui.get_allocated_width() - 2 * self._padding + height = self._gui.get_allocated_height() - 2 * self._padding + + if self._fill_color is not None and self._fill_alpha is not None: + fill = (*self._fill_color, self._fill_alpha * 255) + painter.set_source_rgba(*fill) + painter.rectangle(x, y, width, height) + painter.fill() + + line = (*self._color, self._alpha) + painter.set_source_rgba(*line) + painter.set_line_width(self._thickness) + painter.rectangle(x, y, width, height) + painter.stroke() + + def _draw_underline(self, painter): + """Called by highlight to draw an underline under the item.""" + + line = (*self._color, self._alpha) + painter.set_source_rgba(*line) + painter.set_line_width(self._thickness) + painter.move_to(0, self._gui.get_allocated_height() - 5) + painter.line_to(self._gui.get_allocated_width(), self._gui.get_allocated_height() - 5) + painter.stroke() + + def highlight(self, x, y, width, height): + """Draws the desired indicator over the specified box.""" + + msg = f"GTK HIGHLIGHTER: x:{x}, y:{y}, width:{width}, height:{height}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + try: + self._gui.move(x - self._padding, y - self._padding) + self._gui.resize(width + 2 * self._padding, height + 2 * self._padding) + except Exception as exc: + error_tokens = ["GTK HIGHLIGHTER: Exception:", exc] + debug.printTokens(debug.LEVEL_INFO, error_tokens, True) + else: + self._gui.show_all() + + def quit(self): + """Quits the highlighter.""" + + msg = "GTK HIGHLIGHTER: Quitting." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._gui.destroy() + self._drawing_area = None + self._gui = None diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event.py new file mode 100644 index 0000000..87fd66a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event.py @@ -0,0 +1,1162 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides support for handling input events.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2011-2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +gi.require_version("Gdk", "3.0") +from gi.repository import Atspi + +import math +import time +from gi.repository import Gdk +from gi.repository import GLib + +from . import debug +from . import keybindings +from . import keynames +from . import messages +from . import cthulhu +from . import cthulhu_state +from . import script_manager +from . import settings +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +KEYBOARD_EVENT = "keyboard" +BRAILLE_EVENT = "braille" +MOUSE_BUTTON_EVENT = "mouse:button" +REMOTE_CONTROLLER_EVENT = "remote controller" + +class InputEvent: + + def __init__(self, eventType): + """Creates a new KEYBOARD_EVENT, BRAILLE_EVENT, or MOUSE_BUTTON_EVENT.""" + + self.type = eventType + self.time = time.time() + self._clickCount = 0 + + def getClickCount(self): + """Return the count of the number of clicks a user has made.""" + + return self._clickCount + + def setClickCount(self): + """Updates the count of the number of clicks a user has made.""" + + pass + +def _getXkbStickyKeysState(): + from subprocess import check_output + + try: + output = check_output(['xkbset', 'q']) + for line in output.decode('ASCII', errors='ignore').split('\n'): + if line.startswith('Sticky-Keys = '): + return line.endswith('On') + except Exception: + pass + return False + +class KeyboardEvent(InputEvent): + + stickyKeys = _getXkbStickyKeysState() + + duplicateCount = 0 + cthulhuModifierPressed = False + + # Whether last press of the Cthulhu modifier was alone + lastCthulhuModifierAlone = False + lastCthulhuModifierAloneTime = None + # Whether the current press of the Cthulhu modifier is alone + currentCthulhuModifierAlone = False + currentCthulhuModifierAloneTime = None + # When the second cthulhu press happened + secondCthulhuModifierTime = None + # Sticky modifiers state, to be applied to the next keyboard event + cthulhuStickyModifiers = 0 + + TYPE_UNKNOWN = "unknown" + TYPE_PRINTABLE = "printable" + TYPE_MODIFIER = "modifier" + TYPE_LOCKING = "locking" + TYPE_FUNCTION = "function" + TYPE_ACTION = "action" + TYPE_NAVIGATION = "navigation" + TYPE_DIACRITICAL = "diacritical" + TYPE_ALPHABETIC = "alphabetic" + TYPE_NUMERIC = "numeric" + TYPE_PUNCTUATION = "punctuation" + TYPE_SPACE = "space" + + GDK_PUNCTUATION_KEYS = [Gdk.KEY_acute, + Gdk.KEY_ampersand, + Gdk.KEY_apostrophe, + Gdk.KEY_asciicircum, + Gdk.KEY_asciitilde, + Gdk.KEY_asterisk, + Gdk.KEY_at, + Gdk.KEY_backslash, + Gdk.KEY_bar, + Gdk.KEY_braceleft, + Gdk.KEY_braceright, + Gdk.KEY_bracketleft, + Gdk.KEY_bracketright, + Gdk.KEY_brokenbar, + Gdk.KEY_cedilla, + Gdk.KEY_cent, + Gdk.KEY_colon, + Gdk.KEY_comma, + Gdk.KEY_copyright, + Gdk.KEY_currency, + Gdk.KEY_degree, + Gdk.KEY_diaeresis, + Gdk.KEY_dollar, + Gdk.KEY_EuroSign, + Gdk.KEY_equal, + Gdk.KEY_exclam, + Gdk.KEY_exclamdown, + Gdk.KEY_grave, + Gdk.KEY_greater, + Gdk.KEY_guillemotleft, + Gdk.KEY_guillemotright, + Gdk.KEY_hyphen, + Gdk.KEY_less, + Gdk.KEY_macron, + Gdk.KEY_minus, + Gdk.KEY_notsign, + Gdk.KEY_numbersign, + Gdk.KEY_paragraph, + Gdk.KEY_parenleft, + Gdk.KEY_parenright, + Gdk.KEY_percent, + Gdk.KEY_period, + Gdk.KEY_periodcentered, + Gdk.KEY_plus, + Gdk.KEY_plusminus, + Gdk.KEY_question, + Gdk.KEY_questiondown, + Gdk.KEY_quotedbl, + Gdk.KEY_quoteleft, + Gdk.KEY_quoteright, + Gdk.KEY_registered, + Gdk.KEY_section, + Gdk.KEY_semicolon, + Gdk.KEY_slash, + Gdk.KEY_sterling, + Gdk.KEY_underscore, + Gdk.KEY_yen] + + GDK_ACCENTED_LETTER_KEYS = [Gdk.KEY_Aacute, + Gdk.KEY_aacute, + Gdk.KEY_Acircumflex, + Gdk.KEY_acircumflex, + Gdk.KEY_Adiaeresis, + Gdk.KEY_adiaeresis, + Gdk.KEY_Agrave, + Gdk.KEY_agrave, + Gdk.KEY_Aring, + Gdk.KEY_aring, + Gdk.KEY_Atilde, + Gdk.KEY_atilde, + Gdk.KEY_Ccedilla, + Gdk.KEY_ccedilla, + Gdk.KEY_Eacute, + Gdk.KEY_eacute, + Gdk.KEY_Ecircumflex, + Gdk.KEY_ecircumflex, + Gdk.KEY_Ediaeresis, + Gdk.KEY_ediaeresis, + Gdk.KEY_Egrave, + Gdk.KEY_egrave, + Gdk.KEY_Iacute, + Gdk.KEY_iacute, + Gdk.KEY_Icircumflex, + Gdk.KEY_icircumflex, + Gdk.KEY_Idiaeresis, + Gdk.KEY_idiaeresis, + Gdk.KEY_Igrave, + Gdk.KEY_igrave, + Gdk.KEY_Ntilde, + Gdk.KEY_ntilde, + Gdk.KEY_Oacute, + Gdk.KEY_oacute, + Gdk.KEY_Ocircumflex, + Gdk.KEY_ocircumflex, + Gdk.KEY_Odiaeresis, + Gdk.KEY_odiaeresis, + Gdk.KEY_Ograve, + Gdk.KEY_ograve, + Gdk.KEY_Ooblique, + Gdk.KEY_ooblique, + Gdk.KEY_Otilde, + Gdk.KEY_otilde, + Gdk.KEY_Uacute, + Gdk.KEY_uacute, + Gdk.KEY_Ucircumflex, + Gdk.KEY_ucircumflex, + Gdk.KEY_Udiaeresis, + Gdk.KEY_udiaeresis, + Gdk.KEY_Ugrave, + Gdk.KEY_ugrave, + Gdk.KEY_Yacute, + Gdk.KEY_yacute] + + def __init__(self, pressed, keycode, keysym, modifiers, text): + """Creates a new InputEvent of type KEYBOARD_EVENT. + + Arguments: + - pressed: True if key is pressed, False if released + - keycode: hardware keycode + - keysym: keysym value + - modifiers: modifier mask + - text: text representation of the key + """ + + super().__init__(KEYBOARD_EVENT) + self.id = keysym + self.type = Atspi.EventType.KEY_PRESSED_EVENT if pressed else Atspi.EventType.KEY_RELEASED_EVENT + self.hw_code = keycode + self.modifiers = modifiers & Gdk.ModifierType.MODIFIER_MASK + if modifiers & (1 << Atspi.ModifierType.NUMLOCK): + self.modifiers |= (1 << Atspi.ModifierType.NUMLOCK) + self.event_string = text + self.keyval_name = Gdk.keyval_name(keysym) + if self.event_string == "": + self.event_string = self.keyval_name + self.timestamp = time.time() * 1000 # Convert to milliseconds + self.is_duplicate = False # Will be set by InputEventManager + self._script = None + self._app = None + self._window = None + self._obj = None + self._handler = None + self._consumer = None + self._should_consume = None + self._consume_reason = None + self._did_consume = None + self._result_reason = None + self._bypassCthulhu = None + self._is_kp_with_numlock = False + + # Some implementors don't populate this field at all. More often than not, + # the event_string and the keyval_name coincide for input events. + if not self.event_string: + self.event_string = self.keyval_name + + # Some implementors do populate the field, but with the keyname rather than + # the printable character. This messes us up with punctuation and other symbols. + if len(self.event_string) > 1 \ + and (self.id in KeyboardEvent.GDK_PUNCTUATION_KEYS or \ + self.id in KeyboardEvent.GDK_ACCENTED_LETTER_KEYS): + self.event_string = chr(self.id) + + # Some implementors don't include numlock in the modifiers. Unfortunately, + # trying to heuristically hack around this just by looking at the event + # is not reliable. Ditto regarding asking Gdk for the numlock state. + if self.keyval_name.startswith("KP"): + if modifiers & (1 << Atspi.ModifierType.NUMLOCK): + self._is_kp_with_numlock = True + + self.keyType = None + self.shouldEcho = False + + # Initialize key type - will be refined later in _finalize_initialization + self._finalize_initialization() + + def _finalize_initialization(self): + """Finalize initialization after object creation. + This is separated to allow InputEventManager to set additional properties first.""" + + if self.is_duplicate: + KeyboardEvent.duplicateCount += 1 + else: + KeyboardEvent.duplicateCount = 0 + + _isPressed = self.type == Atspi.EventType.KEY_PRESSED_EVENT + role = AXObject.get_role(self._obj) if self._obj else None + _mayEcho = _isPressed or role == Atspi.Role.TERMINAL + + if KeyboardEvent.stickyKeys and not self.isCthulhuModifier() \ + and not KeyboardEvent.lastCthulhuModifierAlone: + doubleEvent = self._getDoubleClickCandidate() + if doubleEvent and \ + doubleEvent.modifiers & keybindings.CTHULHU_MODIFIER_MASK: + # this is the second event of a double-click, and sticky Cthulhu + # affected the first, so copy over the modifiers to the second + KeyboardEvent.cthulhuStickyModifiers = doubleEvent.modifiers + + if not self.isCthulhuModifier(): + if KeyboardEvent.cthulhuModifierPressed: + KeyboardEvent.currentCthulhuModifierAlone = False + KeyboardEvent.currentCthulhuModifierAloneTime = None + else: + KeyboardEvent.lastCthulhuModifierAlone = False + KeyboardEvent.lastCthulhuModifierAloneTime = None + + if self.isNavigationKey(): + self.keyType = KeyboardEvent.TYPE_NAVIGATION + self.shouldEcho = _mayEcho and settings.enableNavigationKeys + elif self.isActionKey(): + self.keyType = KeyboardEvent.TYPE_ACTION + self.shouldEcho = _mayEcho and settings.enableActionKeys + elif self.isModifierKey(): + self.keyType = KeyboardEvent.TYPE_MODIFIER + self.shouldEcho = _mayEcho and settings.enableModifierKeys + if self.isCthulhuModifier() and not self.is_duplicate: + now = time.time() + if KeyboardEvent.lastCthulhuModifierAlone: + if _isPressed: + KeyboardEvent.secondCthulhuModifierTime = now + if (KeyboardEvent.secondCthulhuModifierTime is not None and + KeyboardEvent.lastCthulhuModifierAloneTime is not None and + KeyboardEvent.secondCthulhuModifierTime < + KeyboardEvent.lastCthulhuModifierAloneTime + 0.5): + # double-cthulhu, let the real action happen + self._bypassCthulhu = True + if not _isPressed: + KeyboardEvent.lastCthulhuModifierAlone = False + KeyboardEvent.lastCthulhuModifierAloneTime = False + else: + KeyboardEvent.cthulhuModifierPressed = _isPressed + if _isPressed: + KeyboardEvent.currentCthulhuModifierAlone = True + KeyboardEvent.currentCthulhuModifierAloneTime = now + else: + KeyboardEvent.lastCthulhuModifierAlone = \ + KeyboardEvent.currentCthulhuModifierAlone + KeyboardEvent.lastCthulhuModifierAloneTime = \ + KeyboardEvent.currentCthulhuModifierAloneTime + elif self.isFunctionKey(): + self.keyType = KeyboardEvent.TYPE_FUNCTION + self.shouldEcho = _mayEcho and settings.enableFunctionKeys + elif self.isDiacriticalKey(): + self.keyType = KeyboardEvent.TYPE_DIACRITICAL + self.shouldEcho = _mayEcho and settings.enableDiacriticalKeys + elif self.isLockingKey(): + self.keyType = KeyboardEvent.TYPE_LOCKING + self.shouldEcho = settings.presentLockingKeys + if self.shouldEcho is None: + self.shouldEcho = not settings.onlySpeakDisplayedText + self.shouldEcho = self.shouldEcho and _isPressed + elif self.isAlphabeticKey(): + self.keyType = KeyboardEvent.TYPE_ALPHABETIC + self.shouldEcho = _mayEcho \ + and (settings.enableAlphabeticKeys or settings.enableEchoByCharacter) + elif self.isNumericKey(): + self.keyType = KeyboardEvent.TYPE_NUMERIC + self.shouldEcho = _mayEcho \ + and (settings.enableNumericKeys or settings.enableEchoByCharacter) + elif self.isPunctuationKey(): + self.keyType = KeyboardEvent.TYPE_PUNCTUATION + self.shouldEcho = _mayEcho \ + and (settings.enablePunctuationKeys or settings.enableEchoByCharacter) + elif self.isSpace(): + self.keyType = KeyboardEvent.TYPE_SPACE + self.shouldEcho = _mayEcho \ + and (settings.enableSpace or settings.enableEchoByCharacter) + else: + self.keyType = KeyboardEvent.TYPE_UNKNOWN + self.shouldEcho = False + + if not self.isLockingKey(): + self.shouldEcho = self.shouldEcho and settings.enableKeyEcho + + if not self.isModifierKey(): + self.setClickCount() + + if cthulhu_state.bypassNextCommand and _isPressed: + KeyboardEvent.cthulhuModifierPressed = False + + if KeyboardEvent.cthulhuModifierPressed: + self.modifiers |= keybindings.CTHULHU_MODIFIER_MASK + + if KeyboardEvent.stickyKeys: + # apply all recorded sticky modifiers + self.modifiers |= KeyboardEvent.cthulhuStickyModifiers + if self.isModifierKey(): + # add this modifier to the sticky ones + KeyboardEvent.cthulhuStickyModifiers |= self.modifiers + else: + # Non-modifier key, so clear the sticky modifiers. If the user + # actually double-presses that key, the modifiers of this event + # will be copied over to the second event, see earlier in this + # function. + KeyboardEvent.cthulhuStickyModifiers = 0 + + self._should_consume, self._consume_reason = self.shouldConsume() + + def _getDoubleClickCandidate(self): + lastEvent = cthulhu_state.lastNonModifierKeyEvent + if isinstance(lastEvent, KeyboardEvent) \ + and lastEvent.event_string == self.event_string \ + and self.time - lastEvent.time <= settings.doubleClickTimeout: + return lastEvent + return None + + def setClickCount(self, count=None): + """Updates the count of the number of clicks a user has made. + + If count is provided, sets the click count to that value. + Otherwise, calculates the click count based on event timing.""" + + if count is not None: + self._clickCount = count + return + + doubleEvent = self._getDoubleClickCandidate() + if not doubleEvent: + self._clickCount = 1 + return + + self._clickCount = doubleEvent.getClickCount() + if self.is_duplicate: + return + + if self.type == Atspi.EventType.KEY_RELEASED_EVENT: + return + + if self._clickCount < 3: + self._clickCount += 1 + return + + self._clickCount = 1 + + def __eq__(self, other): + if not other: + return False + + if self.type == other.type and self.hw_code == other.hw_code: + return self.timestamp == other.timestamp + + return False + + def __str__(self): + if self._shouldObscure(): + keyid = hw_code = modifiers = event_string = keyval_name = key_type = "*" + else: + keyid = self.id + hw_code = self.hw_code + modifiers = self.modifiers + event_string = self.event_string + keyval_name = self.keyval_name + key_type = self.keyType + + return (f"KEYBOARD_EVENT: type={self.type.value_name.upper()}\n") \ + + f" id={keyid}\n" \ + + f" hw_code={hw_code}\n" \ + + f" modifiers={modifiers}\n" \ + + f" event_string=({event_string})\n" \ + + f" keyval_name=({keyval_name})\n" \ + + (" timestamp=%d\n" % self.timestamp) \ + + f" time={time.time():f}\n" \ + + f" keyType={key_type}\n" \ + + f" clickCount={self._clickCount}\n" \ + + f" shouldEcho={self.shouldEcho}\n" + + def _shouldObscure(self): + if not AXUtilities.is_password_text(self._obj): + return False + + if not self.isPrintableKey(): + return False + + if self.modifiers & keybindings.CTRL_MODIFIER_MASK \ + or self.modifiers & keybindings.ALT_MODIFIER_MASK \ + or self.modifiers & keybindings.CTHULHU_MODIFIER_MASK: + return False + + return True + + def _isReleaseForLastNonModifierKeyEvent(self): + last = cthulhu_state.lastNonModifierKeyEvent + if not last: + return False + + if not last.isPressedKey() or self.isPressedKey(): + return False + + if self.id == last.id and self.hw_code == last.hw_code: + return self.modifiers == last.modifiers + + return False + + def isReleaseFor(self, other): + """Return True if this is the release event for other.""" + + if not other: + return False + + if not other.isPressedKey() or self.isPressedKey(): + return False + + return self.id == other.id \ + and self.hw_code == other.hw_code \ + and self.modifiers == other.modifiers \ + and self.event_string == other.event_string \ + and self.keyval_name == other.keyval_name \ + and self.keyType == other.keyType \ + and self._clickCount == other._clickCount + + def isNavigationKey(self): + """Return True if this is a navigation key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_NAVIGATION + + return self.event_string in \ + ["Left", "Right", "Up", "Down", "Home", "End"] + + def isActionKey(self): + """Return True if this is an action key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_ACTION + + return self.event_string in \ + ["Return", "Escape", "Tab", "BackSpace", "Delete", + "Page_Up", "Page_Down"] + + def isAlphabeticKey(self): + """Return True if this is an alphabetic key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_ALPHABETIC + + if not len(self.event_string) == 1: + return False + + return self.event_string.isalpha() + + def isDiacriticalKey(self): + """Return True if this is a non-spacing diacritical key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_DIACRITICAL + + return self.event_string.startswith("dead_") + + def isFunctionKey(self): + """Return True if this is a function key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_FUNCTION + + return self.event_string in \ + ["F1", "F2", "F3", "F4", "F5", "F6", + "F7", "F8", "F9", "F10", "F11", "F12"] + + def isLockingKey(self): + """Return True if this is a locking key.""" + + if self.keyType: + return self.keyType in KeyboardEvent.TYPE_LOCKING + + lockingKeys = ["Caps_Lock", "Shift_Lock", "Num_Lock", "Scroll_Lock"] + if self.event_string not in lockingKeys: + return False + + if not cthulhu_state.bypassNextCommand and not self._bypassCthulhu: + return self.event_string not in settings.cthulhuModifierKeys + + return True + + def isModifierKey(self): + """Return True if this is a modifier key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_MODIFIER + + if self.isCthulhuModifier(): + return True + + return self.event_string in \ + ['Alt_L', 'Alt_R', 'Control_L', 'Control_R', + 'Shift_L', 'Shift_R', 'Meta_L', 'Meta_R', + 'ISO_Level3_Shift'] + + def isNumericKey(self): + """Return True if this is a numeric key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_NUMERIC + + if not len(self.event_string) == 1: + return False + + return self.event_string.isnumeric() + + def isCthulhuModifier(self, checkBypassMode=True): + """Return True if this is the Cthulhu modifier key.""" + + if checkBypassMode and cthulhu_state.bypassNextCommand: + return False + + if self.event_string in settings.cthulhuModifierKeys: + return True + + if self.keyval_name == "KP_0" \ + and "KP_Insert" in settings.cthulhuModifierKeys \ + and self.modifiers & keybindings.SHIFT_MODIFIER_MASK: + return True + + return False + + def isCthulhuModified(self): + """Return True if this key is Cthulhu modified.""" + + if cthulhu_state.bypassNextCommand: + return False + + return self.modifiers & keybindings.CTHULHU_MODIFIER_MASK + + def isKeyPadKeyWithNumlockOn(self): + """Return True if this is a key pad key with numlock on.""" + + return self._is_kp_with_numlock + + def isPrintableKey(self): + """Return True if this is a printable key.""" + + if self.event_string in ["space", " "]: + return True + + if not len(self.event_string) == 1: + return False + + return self.event_string.isprintable() + + def isPressedKey(self): + """Returns True if the key is pressed""" + + return self.type == Atspi.EventType.KEY_PRESSED_EVENT + + def isPunctuationKey(self): + """Return True if this is a punctuation key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_PUNCTUATION + + if not len(self.event_string) == 1: + return False + + if self.isAlphabeticKey() or self.isNumericKey(): + return False + + return self.event_string.isprintable() and not self.event_string.isspace() + + def isSpace(self): + """Return True if this is the space key.""" + + if self.keyType: + return self.keyType == KeyboardEvent.TYPE_SPACE + + return self.event_string in ["space", " "] + + def isFromApplication(self, app): + """Return True if this is associated with the specified app.""" + + return self._app == app + + def isCharacterEchoable(self): + """Returns True if the script will echo this event as part of + character echo. We do this to not double-echo a given printable + character.""" + + if not self.isPrintableKey(): + return False + + script = cthulhu_state.activeScript + return script and script.utilities.willEchoCharacter(self) + + def getLockingState(self): + """Returns True if the event locked a locking key, False if the + event unlocked a locking key, and None if we do not know or this + is not a locking key.""" + + if not self.isLockingKey(): + return None + + if self.event_string == "Caps_Lock": + mod = Atspi.ModifierType.SHIFTLOCK + elif self.event_string == "Shift_Lock": + mod = Atspi.ModifierType.SHIFT + elif self.event_string == "Num_Lock": + mod = Atspi.ModifierType.NUMLOCK + else: + return None + + return not self.modifiers & (1 << mod) + + def getLockingStateString(self): + """Returns the string which reflects the locking state we wish to + include when presenting a locking key.""" + + locked = self.getLockingState() + if locked is None: + return '' + + if not locked: + return messages.LOCKING_KEY_STATE_OFF + + return messages.LOCKING_KEY_STATE_ON + + def getKeyName(self): + """Returns the string to be used for presenting the key to the user.""" + + return keynames.getKeyName(self.event_string) + + def getObject(self): + """Returns the object believed to be associated with this key event.""" + + return self._obj + + def setObject(self, obj): + """Sets the object believed to be associated with this key event.""" + + self._obj = obj + + def getWindow(self): + """Returns the window associated with this key event.""" + + return self._window + + def setWindow(self, window): + """Sets the window associated with this key event.""" + + self._window = window + + def getScript(self): + """Returns the script associated with this key event.""" + + return self._script + + def setScript(self, script): + """Sets the script associated with this key event.""" + + self._script = script + if script: + self._app = script.app + + def getClickCount(self): + """Returns the click count for this event.""" + + return self._clickCount + + def asSingleLineString(self): + """Returns a single-line string representation of this event.""" + + return f"KeyboardEvent({self.keyval_name}, pressed={self.isPressedKey()}, modifiers={self.modifiers})" + + def getHandler(self): + """Returns the handler associated with this key event.""" + + return self._handler + + def _getUserHandler(self): + # TODO - JD: This should go away once plugin support is in place. + try: + bindings = settings.keyBindingsMap.get(self._script.__module__) + except Exception: + bindings = None + if not bindings: + try: + bindings = settings.keyBindingsMap.get("default") + except Exception: + bindings = None + + try: + handler = bindings.getInputHandler(self) + except Exception: + handler = None + + return handler + + def shouldConsume(self): + """Returns True if this event should be consumed.""" + + if not self.timestamp: + return False, 'No timestamp' + + if not self._script: + return False, 'No active script when received' + + if self.is_duplicate: + return False, 'Is duplicate' + + if cthulhu_state.capturingKeys: + return False, 'Capturing keys' + + if cthulhu_state.bypassNextCommand: + return False, 'Bypass next command' + + self._handler = self._getUserHandler() \ + or self._script.keyBindings.getInputHandler(self) + + # TODO - JD: Right now we need to always call consumesKeyboardEvent() + # because that method is updating state, even in instances where there + # is no handler. + scriptConsumes = self._script.consumesKeyboardEvent(self) + + if self._isReleaseForLastNonModifierKeyEvent(): + return scriptConsumes, 'Is release for last non-modifier keyevent' + + if self._script.learnModePresenter.is_active(): + self._consumer = self._script.learnModePresenter.handle_event + return True, 'In Learn Mode' + + if self.isModifierKey(): + if not self.isCthulhuModifier(): + return False, 'Non-Cthulhu modifier not in Learn Mode' + return True, 'Cthulhu modifier' + + if not self._handler: + return False, 'No handler' + + return scriptConsumes, 'Script indication' + + def didConsume(self): + """Returns True if this event was consumed.""" + + if self._did_consume is not None: + return self._did_consume + + return False + + def isHandledBy(self, method): + if not self._handler: + return False + + return method.__func__ == self._handler.function + + def _present(self, inputEvent=None): + if self.isPressedKey(): + self._script.presentationInterrupt() + + if self._script.learnModePresenter.is_active(): + return False + + return self._script.presentKeyboardEvent(self) + + def process(self): + """Processes this input event.""" + + startTime = time.time() + if not self._shouldObscure(): + data = "'%s' (%d)" % (self.event_string, self.hw_code) + else: + data = "(obscured)" + + if self.is_duplicate: + data = '%s DUPLICATE EVENT #%i' % (data, KeyboardEvent.duplicateCount) + + msg = f'\nvvvvv PROCESS {self.type.value_name.upper()}: {data} vvvvv' + debug.printMessage(debug.LEVEL_INFO, msg, False) + + tokens = ["HOST_APP:", self._app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + tokens = ["WINDOW:", self._window] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + tokens = ["LOCATION:", self._obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + tokens = ["CONSUME:", self._should_consume, self._consume_reason] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._did_consume, self._result_reason = self._process() + + if self._should_consume != self._did_consume: + tokens = ["CONSUMED:", self._did_consume, self._result_reason] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if debug.LEVEL_INFO >= debug.debugLevel and cthulhu_state.activeScript: + attributes = cthulhu_state.activeScript.getTransferableAttributes() + for key, value in attributes.items(): + msg = f"INPUT EVENT: {key}: {value}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + msg = f"TOTAL PROCESSING TIME: {time.time() - startTime:.4f}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + msg = f"^^^^^ PROCESS {self.type.value_name.upper()}: {data} ^^^^^\n" + debug.printMessage(debug.LEVEL_INFO, msg, False) + + return self._did_consume + + def _process(self): + """Processes this input event.""" + + if self._bypassCthulhu: + if (self.event_string == "Caps_Lock" \ + or self.event_string == "Shift_Lock") \ + and self.type == Atspi.EventType.KEY_PRESSED_EVENT: + self._lock_mod() + self.keyType = KeyboardEvent.TYPE_LOCKING + self._present() + return False, 'Bypassed cthulhu modifier' + + cthulhu_state.lastInputEvent = self + if not self.isModifierKey(): + cthulhu_state.lastNonModifierKeyEvent = self + + if not self._script: + return False, 'No active script' + + if self.is_duplicate: + return False, 'Is duplicate' + + self._present() + + if not self.isPressedKey(): + return self._should_consume, 'Consumed based on handler' + + if cthulhu_state.capturingKeys: + return False, 'Capturing keys' + + if self.isCthulhuModifier(): + return True, 'Cthulhu modifier' + + if cthulhu_state.bypassNextCommand: + if not self.isModifierKey(): + cthulhu_state.bypassNextCommand = False + self._script.addKeyGrabs() + return False, 'Bypass next command' + + if not self._should_consume: + return False, 'Should not consume' + + if not (self._consumer or self._handler): + return False, 'No consumer or handler' + + if self._consumer or self._handler.function: + GLib.timeout_add(1, self._consume) + return True, 'Will be consumed' + + return False, 'Unaddressed case' + + def _lock_mod(self): + def lock_mod(modifiers, modifier): + def lockit(): + try: + if modifiers & modifier: + lock = Atspi.KeySynthType.UNLOCKMODIFIERS + debug.printMessage(debug.LEVEL_INFO, "Unlocking capslock", True) + else: + lock = Atspi.KeySynthType.LOCKMODIFIERS + debug.printMessage(debug.LEVEL_INFO, "Locking capslock", True) + Atspi.generate_keyboard_event(modifier, "", lock) + debug.printMessage(debug.LEVEL_INFO, "Done with capslock", True) + except Exception: + debug.printMessage(debug.LEVEL_INFO, "Could not trigger capslock, " \ + "at-spi2-core >= 2.32 is needed for triggering capslock", True) + pass + return lockit + if self.event_string == "Caps_Lock": + modifier = 1 << Atspi.ModifierType.SHIFTLOCK + elif self.event_string == "Shift_Lock": + modifier = 1 << Atspi.ModifierType.SHIFT + else: + tokens = ["Unknown locking key", self.event_string] + debug.printTokens(debug.LEVEL_WARNING, tokens, True) + return + debug.printMessage(debug.LEVEL_INFO, "Scheduling capslock", True) + GLib.timeout_add(1, lock_mod(self.modifiers, modifier)) + + def _consume(self): + startTime = time.time() + data = "'%s' (%d)" % (self.event_string, self.hw_code) + msg = f'vvvvv CONSUME {self.type.value_name.upper()}: {data} vvvvv' + debug.printMessage(debug.LEVEL_INFO, msg, False) + + if self._consumer: + msg = f'INFO: Consumer is {self._consumer.__name__}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._consumer(self) + elif self._handler.function: + msg = f'INFO: Handler is {self._handler.description}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._handler.function(self._script, self) + else: + msg = 'INFO: No handler or consumer' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + msg = f'TOTAL PROCESSING TIME: {time.time() - startTime:.4f}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + msg = f'^^^^^ CONSUME {self.type.value_name.upper()}: {data} ^^^^^' + debug.printMessage(debug.LEVEL_INFO, msg, False) + + return False + +class BrailleEvent(InputEvent): + + def __init__(self, event): + """Creates a new InputEvent of type BRAILLE_EVENT. + + Arguments: + - event: the integer BrlTTY command for this event. + """ + super().__init__(BRAILLE_EVENT) + self.event = event + +class MouseButtonEvent(InputEvent): + + try: + display = Gdk.Display.get_default() + seat = Gdk.Display.get_default_seat(display) + _pointer = seat.get_pointer() + except Exception: + _pointer = None + + def __init__(self, event): + """Creates a new InputEvent of type MOUSE_BUTTON_EVENT.""" + + super().__init__(MOUSE_BUTTON_EVENT) + self.x = event.detail1 + self.y = event.detail2 + self.pressed = event.type.endswith('p') + self.button = event.type[len("mouse:button:"):-1] + self._script = cthulhu_state.activeScript + self.window = cthulhu_state.activeWindow + self.obj = None + + if self.pressed: + self._validateCoordinates() + + if not self._script: + return + + if not self._script.utilities.canBeActiveWindow(self.window): + self.window = self._script.utilities.activeWindow() + + if not self.window: + return + + self.obj = self._script.utilities.descendantAtPoint( + self.window, self.x, self.y, event.any_data) + + def _validateCoordinates(self): + if not self._pointer: + return + + screen, x, y = self._pointer.get_position() + if math.sqrt((self.x - x)**2 + (self.y - y)**2) < 25: + return + + msg = ( + f"WARNING: Event coordinates ({self.x}, {self.y}) may be bogus. " + f"Updating to ({x}, {y})" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.x, self.y = x, y + + def setClickCount(self): + """Updates the count of the number of clicks a user has made.""" + + if not self.pressed: + return + + lastInputEvent = cthulhu_state.lastInputEvent + if not isinstance(lastInputEvent, MouseButtonEvent): + self._clickCount = 1 + return + + if self.time - lastInputEvent.time < settings.doubleClickTimeout \ + and lastInputEvent.button == self.button: + if self._clickCount < 2: + self._clickCount += 1 + return + + self._clickCount = 1 + + +class RemoteControllerEvent(InputEvent): + """A simple input event whose main purpose is identification of the origin.""" + + def __init__(self): + super().__init__(REMOTE_CONTROLLER_EVENT) + + +class InputEventHandler: + + def __init__(self, function, description, learnModeEnabled=True): + """Creates a new InputEventHandler instance. All bindings + (e.g., key bindings and braille bindings) will be handled + by an instance of an InputEventHandler. + + Arguments: + - function: the function to call with an InputEvent instance as its + sole argument. The function is expected to return True + if it consumes the event; otherwise it should return + False + - description: a localized string describing what this InputEvent + does + - learnModeEnabled: if True, the description will be spoken and + brailled if learn mode is enabled. If False, + the function will be called no matter what. + """ + + self.function = function + self.description = description + self.learnModeEnabled = learnModeEnabled + + def __eq__(self, other): + """Compares one input handler to another.""" + + if not other: + return False + + return (self.function == other.function) + + def processInputEvent(self, script, inputEvent): + """Processes an input event. + + This function is expected to return True if it consumes the + event; otherwise it is expected to return False. + + Arguments: + - script: the script (if any) associated with this event + - inputEvent: the input event to pass to the function bound + to this InputEventHandler instance. + """ + + consumed = False + try: + consumed = self.function(script, inputEvent) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + return consumed diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event_manager.py new file mode 100644 index 0000000..959a2d8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/input_event_manager.py @@ -0,0 +1,431 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2024 Igalia, S.L. +# Copyright (c) 2024 GNOME Foundation 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. + +"""Provides utilities for managing input events.""" + +from __future__ import annotations + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2024 Stormux" \ + "Copyright (c) 2024 Igalia, S.L." \ + "Copyright (c) 2024 GNOME Foundation Inc." +__license__ = "LGPL" + +from typing import TYPE_CHECKING + +import gi +gi.require_version("Atspi", "2.0") +gi.require_version("Gdk", "3.0") +from gi.repository import Atspi +from gi.repository import Gdk + +from . import debug +from . import input_event +from . import script_manager +from . import settings +from . import cthulhu_state +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +if TYPE_CHECKING: + from . import keybindings + +class InputEventManager: + """Provides utilities for managing input events.""" + + def __init__(self) -> None: + self._last_input_event: input_event.InputEvent | None = None + self._last_non_modifier_key_event: input_event.KeyboardEvent | None = None + self._device: Atspi.Device | None = None + self._mapped_keycodes: list[int] = [] + self._mapped_keysyms: list[int] = [] + self._grabbed_bindings: dict[int, keybindings.KeyBinding] = {} + self._paused: bool = False + + def start_key_watcher(self) -> None: + """Starts the watcher for keyboard input events.""" + + msg = "INPUT EVENT MANAGER: Starting key watcher." + debug.printMessage(debug.LEVEL_INFO, msg, True) + try: + atspi_version = Atspi.get_version() + debug.printMessage(debug.LEVEL_INFO, f"INPUT EVENT MANAGER: AT-SPI version: {atspi_version}", True) + if atspi_version >= (2, 55, 90): + debug.printMessage(debug.LEVEL_INFO, "INPUT EVENT MANAGER: Using Device.new_full", True) + self._device = Atspi.Device.new_full("org.stormux.Cthulhu") + else: + debug.printMessage(debug.LEVEL_INFO, "INPUT EVENT MANAGER: Using Device.new", True) + self._device = Atspi.Device.new() + debug.printMessage(debug.LEVEL_INFO, f"INPUT EVENT MANAGER: Device created: {self._device}", True) + debug.printMessage(debug.LEVEL_INFO, f"INPUT EVENT MANAGER: About to add key watcher callback", True) + result = self._device.add_key_watcher(self.process_keyboard_event) + debug.printMessage(debug.LEVEL_INFO, f"INPUT EVENT MANAGER: add_key_watcher result: {result}", True) + debug.printMessage(debug.LEVEL_INFO, "INPUT EVENT MANAGER: Key watcher added successfully", True) + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"INPUT EVENT MANAGER: Error in start_key_watcher: {e}", True) + raise + + def stop_key_watcher(self) -> None: + """Stops the watcher for keyboard input events.""" + + msg = "INPUT EVENT MANAGER: Stopping key watcher." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._device = None + + def pause_key_watcher(self, pause: bool = True, reason: str = "") -> None: + """Pauses processing of keyboard input events.""" + + msg = f"INPUT EVENT MANAGER: Pause processing: {pause}. {reason}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._paused = pause + + def check_grabbed_bindings(self) -> None: + """Checks the grabbed key bindings.""" + + msg = f"INPUT EVENT MANAGER: {len(self._grabbed_bindings)} grabbed key bindings." + debug.printMessage(debug.LEVEL_INFO, msg, True) + for grab_id, binding in self._grabbed_bindings.items(): + msg = f"INPUT EVENT MANAGER: {grab_id} for: {binding}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def add_grabs_for_keybinding(self, binding: keybindings.KeyBinding) -> list[int]: + """Adds grabs for binding if it is enabled, returns grab IDs.""" + + if not (binding.is_enabled() and binding.is_bound()): + return [] + + if binding.has_grabs(): + tokens = ["INPUT EVENT MANAGER:", binding, "already has grabs."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + if self._device is None: + tokens = ["INPUT EVENT MANAGER: No device to add grab for", binding] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + grab_ids = [] + for kd in binding.key_definitions(): + grab_id = self._device.add_key_grab(kd, None) + grab_ids.append(grab_id) + self._grabbed_bindings[grab_id] = binding + + return grab_ids + + def remove_grabs_for_keybinding(self, binding: keybindings.KeyBinding) -> None: + """Removes grabs for binding.""" + + if self._device is None: + tokens = ["INPUT EVENT MANAGER: No device to remove grab from", binding] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + grab_ids = binding.get_grab_ids() + if not grab_ids: + tokens = ["INPUT EVENT MANAGER:", binding, "doesn't have grabs to remove."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + for grab_id in grab_ids: + self._device.remove_key_grab(grab_id) + removed = self._grabbed_bindings.pop(grab_id, None) + if removed is None: + msg = f"INPUT EVENT MANAGER: No key binding for grab id {grab_id}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def map_keycode_to_modifier(self, keycode: int) -> int: + """Maps keycode as a modifier, returns the newly-mapped modifier.""" + + if self._device is None: + msg = f"INPUT EVENT MANAGER: No device to map keycode {keycode} to modifier" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return 0 + + self._mapped_keycodes.append(keycode) + return self._device.map_modifier(keycode) + + def map_keysym_to_modifier(self, keysym: int) -> int: + """Maps keysym as a modifier, returns the newly-mapped modifier.""" + + if self._device is None: + msg = f"INPUT EVENT MANAGER: No device to map keysym {keysym} to modifier" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return 0 + + self._mapped_keysyms.append(keysym) + return self._device.map_keysym_modifier(keysym) + + def unmap_all_modifiers(self) -> None: + """Unmaps all previously mapped modifiers.""" + + if self._device is None: + msg = "INPUT EVENT MANAGER: No device to unmap all modifiers from" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + for keycode in self._mapped_keycodes: + self._device.unmap_modifier(keycode) + + for keysym in self._mapped_keysyms: + self._device.unmap_keysym_modifier(keysym) + + self._mapped_keycodes.clear() + self._mapped_keysyms.clear() + + def add_grab_for_modifier(self, modifier: str, keysym: int, keycode: int) -> int: + """Adds grab for modifier, returns grab id.""" + + if self._device is None: + msg = f"INPUT EVENT MANAGER: No device to add grab for {modifier}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return -1 + + kd = Atspi.KeyDefinition() + kd.keysym = keysym + kd.keycode = keycode + kd.modifiers = 0 + grab_id = self._device.add_key_grab(kd) + + msg = f"INPUT EVENT MANAGER: Grab id for {modifier}: {grab_id}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return grab_id + + def remove_grab_for_modifier(self, modifier: str, grab_id: int) -> None: + """Removes grab for modifier.""" + + if self._device is None: + msg = f"INPUT EVENT MANAGER: No device to remove grab from {modifier}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + self._device.remove_key_grab(grab_id) + msg = f"INPUT EVENT MANAGER: Grab id removed for {modifier}: {grab_id}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def grab_keyboard(self, reason: str = "") -> None: + """Grabs the keyboard, e.g. when entering learn mode.""" + + msg = "INPUT EVENT MANAGER: Grabbing keyboard" + if reason: + msg += f" Reason: {reason}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + Atspi.Device.grab_keyboard(self._device) + + def ungrab_keyboard(self, reason: str = "") -> None: + """Removes keyboard grab, e.g. when exiting learn mode.""" + + msg = "INPUT EVENT MANAGER: Ungrabbing keyboard" + if reason: + msg += f" Reason: {reason}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + Atspi.Device.ungrab_keyboard(self._device) + + def process_braille_event(self, event: Atspi.Event) -> bool: + """Processes this Braille event.""" + + braille_event = input_event.BrailleEvent(event) + result = braille_event.process() + self._last_input_event = braille_event + self._last_non_modifier_key_event = None + return result + + def process_mouse_button_event(self, event: Atspi.Event) -> None: + """Processes this Mouse event.""" + + mouse_event = input_event.MouseButtonEvent(event) + mouse_event.setClickCount(self._determine_mouse_event_click_count(mouse_event)) + self._last_input_event = mouse_event + + def process_keyboard_event(self, _device, pressed, keycode, keysym, modifiers, text): + """Processes this Atspi keyboard event.""" + + debug.printMessage(debug.LEVEL_INFO, f"INPUT EVENT MANAGER: Received keyboard event: pressed={pressed}, keycode={keycode}, keysym={keysym}, text='{text}'", True) + + if self._paused: + msg = "INPUT EVENT MANAGER: Keyboard event processing is paused." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + # Handle Cthulhu-specific logic before creating event + if not pressed and text == "Num_Lock" and "KP_Insert" in settings.cthulhuModifierKeys \ + and cthulhu_state.activeScript is not None: + cthulhu_state.activeScript.refreshKeyGrabs() + + if pressed: + cthulhu_state.openingDialog = (text == "space" \ + and (modifiers & ~(1 << Atspi.ModifierType.NUMLOCK))) + + event = input_event.KeyboardEvent(pressed, keycode, keysym, modifiers, text or "") + if event in [self._last_input_event, self._last_non_modifier_key_event]: + msg = "INPUT EVENT MANAGER: Received duplicate event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if pressed: + # Get active window and focus + window = cthulhu_state.activeWindow + # Use cthulhu_state.activeScript instead of ScriptManager API + active_script = cthulhu_state.activeScript + if active_script and hasattr(active_script, 'utilities') and hasattr(active_script.utilities, 'canBeActiveWindow'): + if not active_script.utilities.canBeActiveWindow(window): + new_window = active_script.utilities.activeWindow() + if new_window is not None: + window = new_window + tokens = ["INPUT EVENT MANAGER: Updating window and active window to", window] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu_state.activeWindow = window + else: + tokens = ["WARNING:", window, "cannot be active window. No alternative found."] + debug.printTokens(debug.LEVEL_WARNING, tokens, True) + + event.setWindow(window) + event.setObject(cthulhu_state.locusOfFocus) + event.setScript(active_script) + elif self.last_event_was_keyboard(): + assert isinstance(self._last_input_event, input_event.KeyboardEvent) + event.setWindow(self._last_input_event.getWindow()) + event.setObject(self._last_input_event.getObject()) + event.setScript(self._last_input_event.getScript()) + else: + event.setWindow(cthulhu_state.activeWindow) + event.setObject(cthulhu_state.locusOfFocus) + event.setScript(cthulhu_state.activeScript) + + # Finalize initialization now that context is set + event._finalize_initialization() + + if not event.is_duplicate: + debug.printMessage(debug.LEVEL_INFO, f"\n{event}") + + event.setClickCount(self._determine_keyboard_event_click_count(event)) + rv = event.process() + + # Do any needed xmodmap handling + from . import cthulhu + cthulhu.updateKeyMap(event) + + if event.isModifierKey(): + if self.is_release_for(event, self._last_input_event): + msg = "INPUT EVENT MANAGER: Clearing last non modifier key event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._last_non_modifier_key_event = None + else: + self._last_non_modifier_key_event = event + self._last_input_event = event + return rv + + def _determine_keyboard_event_click_count(self, event: input_event.KeyboardEvent) -> int: + """Determines the click count of event.""" + + if not self.last_event_was_keyboard(): + return 1 + + if event.isModifierKey(): + last_event = self._last_input_event + else: + last_event = self._last_non_modifier_key_event or self._last_input_event + + assert isinstance(last_event, input_event.KeyboardEvent) + if (event.time - last_event.time > settings.doubleClickTimeout) or \ + (event.keyval_name != last_event.keyval_name) or \ + (event.getObject() != last_event.getObject()): + return 1 + + last_count = last_event.getClickCount() + if not event.isPressedKey(): + return last_count + if last_event.isPressedKey(): + return last_count + if (event.isModifierKey() and last_count == 2) or last_count == 3: + return 1 + return last_count + 1 + + def _determine_mouse_event_click_count(self, event: input_event.MouseButtonEvent) -> int: + """Determines the click count of event.""" + + if not self.last_event_was_mouse_button(): + return 1 + + assert isinstance(self._last_input_event, input_event.MouseButtonEvent) + if not event.pressed: + return self._last_input_event.getClickCount() + if self._last_input_event.button != event.button: + return 1 + if event.time - self._last_input_event.time > settings.doubleClickTimeout: + return 1 + + return self._last_input_event.getClickCount() + 1 + + def last_event_was_keyboard(self) -> bool: + """Returns True if the last event is a keyboard event.""" + + return isinstance(self._last_input_event, input_event.KeyboardEvent) + + def last_event_was_mouse_button(self) -> bool: + """Returns True if the last event is a mouse button event.""" + + return isinstance(self._last_input_event, input_event.MouseButtonEvent) + + def is_release_for(self, event1, event2): + """Returns True if event1 is a release for event2.""" + + if event1 is None or event2 is None: + return False + + if not isinstance(event1, input_event.KeyboardEvent) \ + or not isinstance(event2, input_event.KeyboardEvent): + return False + + if event1.isPressedKey() or not event2.isPressedKey(): + return False + + result = event1.id == event2.id \ + and event1.hw_code == event2.hw_code \ + and event1.keyval_name == event2.keyval_name + + if result and not event1.isModifierKey(): + result = event1.modifiers == event2.modifiers + + msg = ( + f"INPUT EVENT MANAGER: {event1.asSingleLineString()} " + f"is release for {event2.asSingleLineString()}: {result}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return result + + def last_event_equals_or_is_release_for_event(self, event): + """Returns True if the last non-modifier event equals, or is the release for, event.""" + + if self._last_non_modifier_key_event is None: + return False + + if event == self._last_non_modifier_key_event: + return True + + return self.is_release_for(self._last_non_modifier_key_event, event) + + +_manager = InputEventManager() +def getManager(): + """Returns the Input Event Manager singleton.""" + return _manager \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keybindings.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keybindings.py new file mode 100644 index 0000000..c3e682e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keybindings.py @@ -0,0 +1,590 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides support for defining keybindings and matching them to input +events.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version('Gdk', '3.0') +gi.require_version('Atspi', '2.0') +from gi.repository import Gdk +from gi.repository import Atspi + +import functools + +from . import debug +from . import settings +from . import cthulhu_state + +from .cthulhu_i18n import _ + +_keysymsCache = {} +_keycodeCache = {} + +MODIFIER_CTHULHU = 8 +NO_MODIFIER_MASK = 0 +ALT_MODIFIER_MASK = 1 << Atspi.ModifierType.ALT +CTRL_MODIFIER_MASK = 1 << Atspi.ModifierType.CONTROL +CTHULHU_MODIFIER_MASK = 1 << MODIFIER_CTHULHU +CTHULHU_ALT_MODIFIER_MASK = (1 << MODIFIER_CTHULHU | + 1 << Atspi.ModifierType.ALT) +CTHULHU_CTRL_MODIFIER_MASK = (1 << MODIFIER_CTHULHU | + 1 << Atspi.ModifierType.CONTROL) +CTHULHU_CTRL_ALT_MODIFIER_MASK = (1 << MODIFIER_CTHULHU | + 1 << Atspi.ModifierType.CONTROL | + 1 << Atspi.ModifierType.ALT) +CTHULHU_SHIFT_MODIFIER_MASK = (1 << MODIFIER_CTHULHU | + 1 << Atspi.ModifierType.SHIFT) +SHIFT_MODIFIER_MASK = 1 << Atspi.ModifierType.SHIFT +SHIFT_ALT_MODIFIER_MASK = (1 << Atspi.ModifierType.SHIFT | + 1 << Atspi.ModifierType.ALT) +CTRL_ALT_MODIFIER_MASK = (1 << Atspi.ModifierType.CONTROL | + 1 << Atspi.ModifierType.ALT) +COMMAND_MODIFIER_MASK = (1 << Atspi.ModifierType.ALT | + 1 << Atspi.ModifierType.CONTROL | + 1 << Atspi.ModifierType.META2 | + 1 << Atspi.ModifierType.META3) +NON_LOCKING_MODIFIER_MASK = (1 << Atspi.ModifierType.SHIFT | + 1 << Atspi.ModifierType.ALT | + 1 << Atspi.ModifierType.CONTROL | + 1 << Atspi.ModifierType.META2 | + 1 << Atspi.ModifierType.META3 | + 1 << MODIFIER_CTHULHU) +defaultModifierMask = NON_LOCKING_MODIFIER_MASK + +def getKeycode(keysym): + """Converts an XKeysym string (e.g., 'KP_Enter') to a keycode that + should match the event.hw_code for key events. + + This whole situation is caused by the fact that Solaris chooses + to give us different keycodes for the same key, and the keypad + is the primary place where this happens: if NumLock is not on, + there is no telling the difference between keypad keys and the + other navigation keys (e.g., arrows, page up/down, etc.). One, + for example, would expect to get KP_End for the '1' key on the + keypad if NumLock were not on. Instead, we get 'End' and the + keycode for it matches the keycode for the other 'End' key. Odd. + If NumLock is on, we at least get KP_* keys. + + So...when setting up keybindings, we say we're interested in + KeySyms, but those keysyms are carefully chosen so as to result + in a keycode that matches the actual key on the keyboard. This + is why we use KP_1 instead of KP_End and so on in our keybindings. + + Arguments: + - keysym: a string that is a valid representation of an XKeysym. + + Returns an integer representing a key code that should match the + event.hw_code for key events. + """ + + if not keysym: + return 0 + + if keysym not in _keycodeCache: + keymap = Gdk.Keymap.get_default() + + # Find the numerical value of the keysym + # + keyval = Gdk.keyval_from_name(keysym) + if keyval == 0: + return 0 + + # Now find the keycodes for the keysym. Since a keysym can + # be associated with more than one key, we'll shoot for the + # keysym that's in group 0, regardless of shift level (each + # entry is of the form [keycode, group, level]). + # + _keycodeCache[keysym] = 0 + success, entries = keymap.get_entries_for_keyval(keyval) + + for entry in entries: + if entry.group == 0: + _keycodeCache[keysym] = entry.keycode + break + if _keycodeCache[keysym] == 0: + _keycodeCache[keysym] = entries[0].keycode + + #print keysym, keyval, entries, _keycodeCache[keysym] + + return _keycodeCache[keysym] + +def getModifierNames(mods): + """Gets the modifier names of a numeric modifier mask as a human + consumable string. + """ + + text = "" + if mods & CTHULHU_MODIFIER_MASK: + if settings.keyboardLayout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP: + # Translators: this is presented in a GUI to represent the + # "insert" key when used as the Cthulhu modifier. + text += _("Insert") + "+" + else: + # Translators: this is presented in a GUI to represent the + # "caps lock" modifier. + text += _("Caps_Lock") + "+" + elif mods & (1 << Atspi.ModifierType.SHIFTLOCK): + # Translators: this is presented in a GUI to represent the + # "caps lock" modifier. + # + text += _("Caps_Lock") + "+" + #if mods & (1 << Atspi.ModifierType.NUMLOCK): + # text += _("Num_Lock") + "+" + if mods & 128: + # Translators: this is presented in a GUI to represent the + # "right alt" modifier. + # + text += _("Alt_R") + "+" + if mods & (1 << Atspi.ModifierType.META3): + # Translators: this is presented in a GUI to represent the + # "super" modifier. + # + text += _("Super") + "+" + if mods & (1 << Atspi.ModifierType.META2): + # Translators: this is presented in a GUI to represent the + # "meta 2" modifier. + # + text += _("Meta2") + "+" + #if mods & (1 << Atspi.ModifierType.META): + # text += _("Meta") + "+" + if mods & ALT_MODIFIER_MASK: + # Translators: this is presented in a GUI to represent the + # "left alt" modifier. + # + text += _("Alt_L") + "+" + if mods & CTRL_MODIFIER_MASK: + # Translators: this is presented in a GUI to represent the + # "control" modifier. + # + text += _("Ctrl") + "+" + if mods & SHIFT_MODIFIER_MASK: + # Translators: this is presented in a GUI to represent the + # "shift " modifier. + # + text += _("Shift") + "+" + return text + +def getClickCountString(count): + """Returns a human-consumable string representing the number of + clicks, such as 'double click' and 'triple click'.""" + + if count == 2: + # Translators: Cthulhu keybindings support double + # and triple "clicks" or key presses, similar to + # using a mouse. + # + return _("double click") + if count == 3: + # Translators: Cthulhu keybindings support double + # and triple "clicks" or key presses, similar to + # using a mouse. + # + return _("triple click") + return "" + +class KeyBinding: + """A single key binding, consisting of a keycode, a modifier mask, + and the InputEventHandler. + """ + + def __init__(self, keysymstring, modifier_mask, modifiers, handler, + click_count = 1): + """Creates a new key binding. + + Arguments: + - keysymstring: the keysymstring - this is typically a string + from /usr/include/X11/keysymdef.h with the preceding 'XK_' + removed (e.g., XK_KP_Enter becomes the string 'KP_Enter'). + - modifier_mask: bit mask where a set bit tells us what modifiers + we care about (see Atspi.ModifierType.*) + - modifiers: the state the modifiers we care about must be in for + this key binding to match an input event (see also + Atspi.ModifierType.*) + - handler: the InputEventHandler for this key binding + """ + + self.keysymstring = keysymstring + self.modifier_mask = modifier_mask + self.modifiers = modifiers + self.handler = handler + self.click_count = click_count + self.keycode = None + + def matches(self, keycode, modifiers): + """Returns true if this key binding matches the given keycode and + modifier state. + """ + + # We lazily bind the keycode. The primary reason for doing this + # is so that atspi does not have to be initialized before setting + # keybindings in the user's preferences file. + # + if not self.keycode: + self.keycode = getKeycode(self.keysymstring) + + # Debug logging for DisplayVersion plugin specifically + if self.keysymstring == 'v' and self.modifiers == 257: + with open('/tmp/displayversion_matches.log', 'a') as f: + f.write(f"=== DisplayVersion matches() debug ===\n") + f.write(f"Self keycode: {self.keycode}\n") + f.write(f"Self keysymstring: {self.keysymstring}\n") + f.write(f"Self modifiers: {self.modifiers}\n") + f.write(f"Self modifier_mask: {self.modifier_mask}\n") + f.write(f"Input keycode: {keycode}\n") + f.write(f"Input modifiers: {modifiers}\n") + f.write(f"Keycode match: {self.keycode == keycode}\n") + if self.keycode == keycode: + result = modifiers & self.modifier_mask + f.write(f"Modifier calculation: {modifiers} & {self.modifier_mask} = {result}\n") + f.write(f"Modifier match: {result == self.modifiers}\n") + f.write(f"Overall match: {self.keycode == keycode and (modifiers & self.modifier_mask) == self.modifiers}\n") + + if self.keycode == keycode: + result = modifiers & self.modifier_mask + return result == self.modifiers + else: + return False + + def description(self): + """Returns the description of this binding's functionality.""" + + try: + return self.handler.description + except Exception: + return '' + + def asString(self): + """Returns a more human-consumable string representing this binding.""" + + mods = getModifierNames(self.modifiers) + clickCount = getClickCountString(self.click_count) + keysym = self.keysymstring + string = f'{mods}{keysym} {clickCount}' + + return string.strip() + + def keyDefs(self): + """ return a list of Atspi key definitions for the given binding. + This may return more than one binding if the Cthulhu modifier is bound + to more than one key. + If AT-SPI is older than 2.40, then this function will not work and + will return an empty set. + """ + ret = [] + if not self.keycode: + self.keycode = getKeycode(self.keysymstring) + + if self.modifiers & CTHULHU_MODIFIER_MASK: + device = cthulhu_state.device + if device is None: + return ret + modList = [] + otherMods = self.modifiers & ~CTHULHU_MODIFIER_MASK + numLockMod = device.get_modifier(getKeycode("Num_Lock")) + lockedMods = device.get_locked_modifiers() + numLockOn = lockedMods & numLockMod + for key in settings.cthulhuModifierKeys: + keycode = getKeycode(key) + if keycode == 0 and key == "Shift_Lock": + keycode = getKeycode("Caps_Lock") + mod = device.map_modifier(keycode) + if key != "KP_Insert" or not numLockOn: + modList.append(mod | otherMods) + else: + modList = [self.modifiers] + for mod in modList: + kd = Atspi.KeyDefinition() + kd.keycode = self.keycode + kd.modifiers = mod + ret.append(kd) + return ret + +class KeyBindings: + """Structure that maintains a set of KeyBinding instances. + """ + + def __init__(self): + self.keyBindings = [] + + def __str__(self): + result = "[\n" + for keyBinding in self.keyBindings: + result += " [%x %x %s %d %s]\n" % \ + (keyBinding.modifier_mask, + keyBinding.modifiers, + keyBinding.keysymstring, + keyBinding.click_count, + keyBinding.handler.description) + result += "]" + return result + + def add(self, keyBinding): + """Adds the given KeyBinding instance to this set of keybindings. + """ + + if keyBinding.keysymstring and self.hasKeyBinding(keyBinding, "keysNoMask"): + msg = ( + f"KEYBINDINGS: '{keyBinding.asString()}' " + f"({keyBinding.description()}) already in keybindings" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.keyBindings.append(keyBinding) + + def remove(self, keyBinding): + """Removes the given KeyBinding instance from this set of keybindings. + """ + + try: + i = self.keyBindings.index(keyBinding) + except Exception: + pass + else: + del self.keyBindings[i] + + def removeByHandler(self, handler): + """Removes the given KeyBinding instance from this set of keybindings. + """ + i = len(self.keyBindings) + while i > 0: + if self.keyBindings[i - 1].handler == handler: + del self.keyBindings[i - 1] + i = i - 1 + + def hasKeyBinding (self, newKeyBinding, typeOfSearch="strict"): + """Return True if keyBinding is already in self.keyBindings. + + The typeOfSearch can be: + "strict": matches description, modifiers, key, and + click count + "description": matches only description. + "keys": matches the modifiers, key, and modifier mask, + and click count + "keysNoMask": matches the modifiers, key, and click count + """ + + hasIt = False + + for keyBinding in self.keyBindings: + if typeOfSearch == "strict": + if (keyBinding.handler.description \ + == newKeyBinding.handler.description) \ + and (keyBinding.keysymstring \ + == newKeyBinding.keysymstring) \ + and (keyBinding.modifier_mask \ + == newKeyBinding.modifier_mask) \ + and (keyBinding.modifiers \ + == newKeyBinding.modifiers) \ + and (keyBinding.click_count \ + == newKeyBinding.click_count): + hasIt = True + elif typeOfSearch == "description": + if keyBinding.handler.description \ + == newKeyBinding.handler.description: + hasIt = True + elif typeOfSearch == "keys": + if (keyBinding.keysymstring \ + == newKeyBinding.keysymstring) \ + and (keyBinding.modifier_mask \ + == newKeyBinding.modifier_mask) \ + and (keyBinding.modifiers \ + == newKeyBinding.modifiers) \ + and (keyBinding.click_count \ + == newKeyBinding.click_count): + hasIt = True + elif typeOfSearch == "keysNoMask": + if (keyBinding.keysymstring \ + == newKeyBinding.keysymstring) \ + and (keyBinding.modifiers \ + == newKeyBinding.modifiers) \ + and (keyBinding.click_count \ + == newKeyBinding.click_count): + hasIt = True + + return hasIt + + def getBoundBindings(self, uniqueOnly=False): + """Returns the KeyBinding instances which are bound to a keystroke. + + Arguments: + - uniqueOnly: Should alternative bindings for the same handler be + filtered out (default: False) + """ + + bound = [kb for kb in self.keyBindings if kb.keysymstring] + if uniqueOnly: + handlers = [kb.handler.description for kb in bound] + bound = [bound[i] for i in map(handlers.index, set(handlers))] + + bindings = {} + for kb in bound: + string = kb.asString() + match = bindings.get(string) + if match is not None: + tokens = ["WARNING: '", string, "' (", kb.description(), ") also matches:", match] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + bindings[string] = kb.description() + + return bound + + def getBindingsForHandler(self, handler): + """Returns the KeyBinding instances associated with handler.""" + + return [kb for kb in self.keyBindings if kb.handler == handler] + + def _checkMatchingBindings(self, keyboardEvent, result): + if debug.debugLevel > debug.LEVEL_INFO: + return + + # If we don't have multiple matches, we're good. + if len(result) <= 1: + return + + # If we have multiple matches, but they have unique click counts, we're good. + if len(set(map(lambda x: x.click_count, result))) == len(result): + return + + def toString(x): + return "%s (%ix)" % (x.handler.description, x.click_count) + + msg = ( + f"KEYBINDINGS: '{keyboardEvent.event_string}' " + f"matches multiple handlers: {', '.join(map(toString, result))}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def getInputHandler(self, keyboardEvent): + """Returns the input handler of the key binding that matches the + given keycode and modifiers, or None if no match exists. + """ + + import logging + logger = logging.getLogger(__name__) + + # Check if this might be the DisplayVersion key combination + event_str = keyboardEvent.event_string if hasattr(keyboardEvent, 'event_string') else 'unknown' + if event_str.lower() == 'v': + logger.info(f"=== KeyBindings.getInputHandler: Looking for handler ===") + logger.info(f"Event string: {event_str}") + logger.info(f"Hardware code: {keyboardEvent.hw_code}") + logger.info(f"Modifiers: {keyboardEvent.modifiers}") + logger.info(f"Total keybindings to check: {len(self.keyBindings)}") + + with open('/tmp/keybinding_lookup.log', 'a') as f: + f.write(f"=== Looking for 'v' key handler ===\n") + f.write(f"Event string: {event_str}\n") + f.write(f"Hardware code: {keyboardEvent.hw_code}\n") + f.write(f"Modifiers: {keyboardEvent.modifiers}\n") + f.write(f"Total keybindings: {len(self.keyBindings)}\n") + + # Log all keybindings for comparison + for i, kb in enumerate(self.keyBindings): + if 'v' in kb.keysymstring.lower() or 'version' in kb.handler.description.lower(): + logger.info(f"Binding {i}: keysym={kb.keysymstring}, modifiers={kb.modifiers}, mask={kb.modifier_mask}, desc={kb.handler.description}") + with open('/tmp/keybinding_lookup.log', 'a') as f: + f.write(f"Found V-related binding {i}: keysym={kb.keysymstring}, modifiers={kb.modifiers}, mask={kb.modifier_mask}, desc={kb.handler.description}\n") + + matches = [] + candidates = [] + clickCount = keyboardEvent.getClickCount() + for keyBinding in self.keyBindings: + if keyBinding.matches(keyboardEvent.hw_code, keyboardEvent.modifiers): + if event_str.lower() == 'v': + logger.info(f"MATCH found! keysym={keyBinding.keysymstring}, desc={keyBinding.handler.description}") + if (keyboardEvent.modifiers & keyBinding.modifier_mask) == keyBinding.modifiers and \ + keyBinding.click_count == clickCount: + matches.append(keyBinding) + # If there's no keysymstring, it's unbound and cannot be + # a match. + # + if keyBinding.keysymstring: + candidates.append(keyBinding) + + if event_str.lower() == 'v': + logger.info(f"Exact matches: {len(matches)}") + logger.info(f"Candidates: {len(candidates)}") + with open('/tmp/keybinding_lookup.log', 'a') as f: + f.write(f"Exact matches: {len(matches)}\n") + f.write(f"Candidates: {len(candidates)}\n") + + self._checkMatchingBindings(keyboardEvent, matches) + if matches: + if event_str.lower() == 'v': + logger.info(f"Returning exact match handler: {matches[0].handler.description}") + return matches[0].handler + + if keyboardEvent.isKeyPadKeyWithNumlockOn(): + return None + + # If we're still here, we don't have an exact match. Prefer + # the one whose click count is closest to, but does not exceed, + # the actual click count. + # + candidates.sort(key=functools.cmp_to_key(lambda x, y: y.click_count - x.click_count)) + self._checkMatchingBindings(keyboardEvent, candidates) + for candidate in candidates: + if candidate.click_count <= clickCount: + if event_str.lower() == 'v': + logger.info(f"Returning candidate handler: {candidate.handler.description}") + return candidate.handler + + if event_str.lower() == 'v': + logger.info("No handler found!") + return None + + def load(self, keymap, handlers): + """ Takes the keymappings and tries to find a matching named + function in handlers. + keymap is a list of lists, each list contains 5 elements + If addUnbound is set to true, then at the end of loading all the + keybindings, any remaining functions will be unbound. + """ + + # TODO - JD: This won't be needed once the remaining bindings have + # been removed from the keymap files. + + for i in keymap: + keysymstring = i[0] + modifierMask = i[1] + modifiers = i[2] + handler = i[3] + try: + clickCount = i[4] + except Exception: + clickCount = 1 + + if handler in handlers: + self.add(KeyBinding( + keysymstring, modifierMask, modifiers, handlers[handler], clickCount)) + else: + tokens = ["KEYBINDINGS: Could not find", handler, "handler for keybinding."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keynames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keynames.py new file mode 100644 index 0000000..8da6411 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/keynames.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Exposes a dictionary, keynames, that maps key events +into localized words.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +from . import chnames + +from .cthulhu_i18n import _ +from .cthulhu_i18n import C_ + +# __keynames is a dictionary where the keys represent a UTF-8 +# string for a keyboard key and the values represent the common +# phrase used to describe the key. +# +__keynames = {} + +# Translators: this is how someone would speak the name of the shift key +# +__keynames["Shift"] = C_("keyboard", "Shift") + +# Translators: this is how someone would speak the name of the alt key +# +__keynames["Alt"] = C_("keyboard", "Alt") + +# Translators: this is how someone would speak the name of the control key +# +__keynames["Control"] = C_("keyboard", "Control") + +# Translators: this is how someone would speak the name of the left shift key +# +__keynames["Shift_L"] = _("left shift") + +# Translators: this is how someone would speak the name of the left alt key +# +__keynames["Alt_L"] = _("left alt") + +# Translators: this is how someone would speak the name of the left ctrl key +# +__keynames["Control_L"] = _("left control") + +# Translators: this is how someone would speak the name of the right shift key +# +__keynames["Shift_R"] = _("right shift") + +# Translators: this is how someone would speak the name of the right alt key +# +__keynames["Alt_R"] = _("right alt") + +# Translators: this is how someone would speak the name of the right ctrl key +# +__keynames["Control_R"] = _("right control") + +# Translators: this is how someone would speak the name of the left meta key +# +__keynames["Meta_L"] = _("left meta") + +# Translators: this is how someone would speak the name of the right meta key +# +__keynames["Meta_R"] = _("right meta") + +# Translators: this is how someone would speak the name of the num lock key +# +__keynames["Num_Lock"] = _("num lock") + +# Translators: this is how someone would speak the name of the caps lock key +# +__keynames["Caps_Lock"] = _("caps lock") + +# Translators: this is how someone would speak the name of the shift lock key +# There is no reason to make it different from the translation for "caps lock" +# +__keynames["Shift_Lock"] = _("shift lock") + +# Translators: this is how someone would speak the name of the scroll lock key +# +__keynames["Scroll_Lock"] = _("scroll lock") + +# Translators: this is how someone would speak the name of the page up key +# +__keynames["Page_Up"] = _("page up") + +# Translators: this is how someone would speak the name of the page up key +# +__keynames["KP_Page_Up"] = _("page up") + +# Translators: this is how someone would speak the name of the page up key +# +__keynames["Prior"] = _("page up") + +# Translators: this is how someone would speak the name of the page up key +# +__keynames["KP_Prior"] = _("page up") + +# Translators: this is how someone would speak the name of the page down key +# +__keynames["Page_Down"] = _("page down") + +# Translators: this is how someone would speak the name of the page down key +# +__keynames["KP_Page_Down"] = _("page down") + +# Translators: this is how someone would speak the name of the page down key +# +__keynames["Next"] = _("page down") + +# Translators: this is how someone would speak the name of the page down key +# +__keynames["KP_Next"] = _("page down") + +# Translators: this is how someone would speak the name of the tab key +# +__keynames["Tab"] = _("tab") + +# Translators: this is how someone would speak the name of the left tab key +# +__keynames["ISO_Left_Tab"] = _("left tab") + +# Translators: this is the spoken word for the space character +# +__keynames["space"] = _("space") + +# Translators: this is how someone would speak the name of the backspace key +# +__keynames["BackSpace"] = _("backspace") + +# Translators: this is how someone would speak the name of the return key +# +__keynames["Return"] = _("return") + +# Translators: this is how someone would speak the name of the enter key +# +__keynames["KP_Enter"] = _("enter") + +# Translators: this is how someone would speak the name of the up arrow key +# +__keynames["Up"] = _("up") + +# Translators: this is how someone would speak the name of the up arrow key +# +__keynames["KP_Up"] = _("up") + +# Translators: this is how someone would speak the name of the down arrow key +# +__keynames["Down"] = _("down") + +# Translators: this is how someone would speak the name of the down arrow key +# +__keynames["KP_Down"] = _("down") + +# Translators: this is how someone would speak the name of the left arrow key +# +__keynames["Left"] = _("left") + +# Translators: this is how someone would speak the name of the left arrow key +# +__keynames["KP_Left"] = _("left") + +# Translators: this is how someone would speak the name of the right arrow key +# +__keynames["Right"] = _("right") + +# Translators: this is how someone would speak the name of the right arrow key +# +__keynames["KP_Right"] = _("right") + +# Translators: this is how someone would speak the name of the left super key +# +__keynames["Super_L"] = _("left super") + +# Translators: this is how someone would speak the name of the right super key +# +__keynames["Super_R"] = _("right super") + +# Translators: this is how someone would speak the name of the menu key +# +__keynames["Menu"] = _("menu") + +# Translators: this is how someone would speak the name of the ISO shift key +# +__keynames["ISO_Level3_Shift"] = _("Alt Gr") + +# Translators: this is how someone would speak the name of the help key +# +__keynames["Help"] = _("help") + +# Translators: this is how someone would speak the name of the multi key +# +__keynames["Multi_key"] = _("multi") + +# Translators: this is how someone would speak the name of the mode switch key +# +__keynames["Mode_switch"] = _("mode switch") + +# Translators: this is how someone would speak the name of the escape key +# +__keynames["Escape"] = _("escape") + +# Translators: this is how someone would speak the name of the insert key +# +__keynames["Insert"] = _("insert") + +# Translators: this is how someone would speak the name of the insert key +# +__keynames["KP_Insert"] = _("insert") + +# Translators: this is how someone would speak the name of the delete key +# +__keynames["Delete"] = _("delete") + +# Translators: this is how someone would speak the name of the delete key +# +__keynames["KP_Delete"] = _("delete") + +# Translators: this is how someone would speak the name of the home key +# +__keynames["Home"] = _("home") + +# Translators: this is how someone would speak the name of the home key +# +__keynames["KP_Home"] = _("home") + +# Translators: this is how someone would speak the name of the end key +# +__keynames["End"] = _("end") + +# Translators: this is how someone would speak the name of the end key +# +__keynames["KP_End"] = _("end") + +# Translators: this is how someone would speak the name of the begin key +# +__keynames["KP_Begin"] = _("begin") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the grave glyph +# +__keynames["dead_grave"] = _("grave") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the acute glyph +# +__keynames["dead_acute"] = _("acute") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the circumflex glyph +# +__keynames["dead_circumflex"] = _("circumflex") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the tilde glyph +# +__keynames["dead_tilde"] = _("tilde") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the diaeresis glyph +# +__keynames["dead_diaeresis"] = _("diaeresis") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the ring glyph +# +__keynames["dead_abovering"] = _("ring") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the cedilla glyph +# +__keynames["dead_cedilla"] = _("cedilla") + +# Translators: this is how someone would speak the name of the +# non-spacing diacritical key for the stroke glyph +# +__keynames["dead_stroke"] = _("stroke") + +# Translators: this is how someone would speak the name of the minus key +# +__keynames["minus"] = _("minus") + +# Translators: this is how someone would speak the name of the plus key +# +__keynames["plus"] = _("plus") + + +def getKeyName(key): + """Given a keyboard key, return its name as people might refer to it + in ordinary conversation. + + Arguments: + - key: the key to get the name for + + Returns a string representing the name for the key + """ + + return __keynames.get(key, chnames.getCharacterName(key)) + +def localizeKeySequence(keys): + """Given a sequence of keys, such as 'Shift Control A', localize the + full sequence. + + Arguments: + - keys: the key sequence to localize + + Returns a string representing the localized version to present to the + user + """ + + keyList = keys.split() + for key in keyList: + keyName = getKeyName(key) + keys = keys.replace(key, keyName) + + return keys diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/label_inference.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/label_inference.py new file mode 100644 index 0000000..2e614d8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/label_inference.py @@ -0,0 +1,616 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Heuristic means to infer the functional/displayed label of a widget.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (C) 2011-2013 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +class LabelInference: + + def __init__(self, script): + """Creates an instance of the LabelInference class. + + Arguments: + - script: the script with which this instance is associated. + """ + + self._script = script + self._lineCache = {} + self._extentsCache = {} + self._isWidgetCache = {} + + def infer(self, obj, focusedOnly=True): + """Attempt to infer the functional/displayed label of obj. + + Arguments + - obj: the unlabeled widget + - focusedOnly: If True, only infer if the widget has focus. + + Returns the text which we think is the label, or None. + """ + + tokens = ["LABEL INFERENCE: Infer label for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not obj: + return None, [] + + if focusedOnly and not AXUtilities.is_focused(obj): + tokens = ["LABEL INFERENCE:", obj, "is not focused"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None, [] + + result, objects = None, [] + if not result: + result, objects = self.inferFromTextLeft(obj) + debug.printMessage(debug.LEVEL_INFO, f"LABEL INFERENCE: Text Left: '{result}'", True) + if not result or self._preferRight(obj): + result, objects = self.inferFromTextRight(obj) or result + debug.printMessage(debug.LEVEL_INFO, f"LABEL INFERENCE: Text Right: '{result}'", True) + if not result: + result, objects = self.inferFromTable(obj) + debug.printMessage(debug.LEVEL_INFO, f"LABEL INFERENCE: Table: '{result}'", True) + if not result: + result, objects = self.inferFromTextAbove(obj) + debug.printMessage(debug.LEVEL_INFO, f"LABEL INFERENCE: Text Above: '{result}'", True) + if not result: + result, objects = self.inferFromTextBelow(obj) + debug.printMessage(debug.LEVEL_INFO, f"LABEL INFERENCE: Text Below: '{result}'", True) + + # TODO - We probably do not wish to "infer" from these. Instead, we + # should ensure that this content gets presented as part of the widget. + # (i.e. the label is something on screen. Widget name and description + # are each something other than a label.) + if not result: + result, objects = AXObject.get_name(obj), [] + debug.printMessage(debug.LEVEL_INFO, f"LABEL INFERENCE: Name: '{result}'", True) + + if result: + result = result.strip() + result = result.replace("\n", " ") + + # Desperate times call for desperate measures.... + if not result: + result, objects = self.inferFromTextLeft(obj, proximity=200) + debug.printMessage( + debug.LEVEL_INFO, + f"LABEL INFERENCE: Text Left with proximity of 200: '{result}'", True) + + self.clearCache() + return result, objects + + def clearCache(self): + """Dumps whatever we've stored for performance purposes.""" + + self._lineCache = {} + self._extentsCache = {} + self._isWidgetCache = {} + + def _preferRight(self, obj): + """Returns True if we should prefer text on the right, rather than the + left, for the object obj.""" + + return AXUtilities.is_check_box(obj) or AXUtilities.is_radio_button(obj) + + def _preventRight(self, obj): + """Returns True if we should not permit inference based on text to + the right for the object obj.""" + + return AXUtilities.is_combo_box(obj) or AXUtilities.is_list_box(obj) + + def _preferTop(self, obj): + """Returns True if we should prefer text above, rather than below for + the object obj.""" + + return AXUtilities.is_combo_box(obj) or AXUtilities.is_list_box(obj) + + def _preventBelow(self, obj): + """Returns True if we should not permit inference based on text below + the object obj.""" + + return not AXUtilities.is_text_input(obj) + + def _isSimpleObject(self, obj): + """Returns True if the given object has 'simple' contents, such as text + without embedded objects or a single embedded object without text.""" + + if obj is None: + return False + + def isMatch(x): + return x is not None \ + and not self._script.utilities.isStaticTextLeaf(x) \ + and not AXUtilities.is_link(x) + + children = [child for child in AXObject.iter_children(obj, isMatch)] + if len(children) > 1: + return False + + try: + text = obj.queryText() + except NotImplementedError: + return True + + string = text.getText(0, -1).strip() + if string.count(self._script.EMBEDDED_OBJECT_CHARACTER) > 1: + return False + + return True + + def _cannotLabel(self, obj): + """Returns True if the given object should not be treated as a label.""" + + if obj is None: + return True + + if AXUtilities.is_heading(obj) or AXUtilities.is_list_item(obj): + return True + + return self._isWidget(obj) + + def _isWidget(self, obj): + """Returns True if the given object is a widget.""" + + if obj is None: + return False + + rv = self._isWidgetCache.get(hash(obj)) + if rv is not None: + return rv + + widgetRoles = [Atspi.Role.CHECK_BOX, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.TOGGLE_BUTTON, + Atspi.Role.COMBO_BOX, + Atspi.Role.LIST, + Atspi.Role.LIST_BOX, + Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.ENTRY, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.PUSH_BUTTON] + + isWidget = AXObject.get_role(obj) in widgetRoles + if not isWidget and AXUtilities.is_editable(obj): + isWidget = True + + self._isWidgetCache[hash(obj)] = isWidget + return isWidget + + def _getExtents(self, obj, startOffset=0, endOffset=-1): + """Returns (x, y, width, height) of the text at the given offsets + if the object implements accessible text, or just the extents of + the object if it doesn't implement accessible text.""" + + if not obj: + return 0, 0, 0, 0 + + rv = self._extentsCache.get((hash(obj), startOffset, endOffset)) + if rv: + return rv + + extents = 0, 0, 0, 0 + text = self._script.utilities.queryNonEmptyText(obj) + if text: + if not AXUtilities.is_text_input(obj): + if endOffset == -1: + try: + endOffset = text.characterCount + except Exception: + tokens = ["LABEL INFERENCE: Exception getting character count for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return extents + + extents = text.getRangeExtents(startOffset, endOffset, 0) + + if not (extents[2] and extents[3]): + try: + ext = obj.queryComponent().getExtents(0) + except NotImplementedError: + tokens = ["LABEL INFERENCE:", obj, "does not implement the component interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception: + tokens = ["LABEL INFERENCE: Exception getting extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + extents = ext.x, ext.y, ext.width, ext.height + + self._extentsCache[(hash(obj), startOffset, endOffset)] = extents + return extents + + def _createLabelFromContents(self, obj): + """Gets the functional label text associated with the object obj.""" + + if not self._isSimpleObject(obj): + return None, [] + + if self._cannotLabel(obj): + return None, [] + + contents = self._script.utilities.getObjectContentsAtOffset(obj, useCache=False) + objects = [content[0] for content in contents] + if list(filter(self._isWidget, objects)): + return None, [] + + strings = [content[3] for content in contents] + return ''.join(strings), objects + + def _getLineContents(self, obj, start=0): + """Get the (obj, startOffset, endOffset, string) tuples for the line + containing the object, obj.""" + + rv = self._lineCache.get(hash(obj)) + if rv: + return rv + + key = hash(obj) + if self._isWidget(obj): + start, end = self._script.utilities.getHyperlinkRange(obj) + obj = AXObject.get_parent(obj) + + rv = self._script.utilities.getLineContentsAtOffset(obj, start, True, False) + self._lineCache[key] = rv + + return rv + + def inferFromTextLeft(self, obj, proximity=75): + """Attempt to infer the functional/displayed label of obj by + looking at the contents of the current line, which are to the + left of this object + + Arguments + - obj: the unlabeled widget + - proximity: pixels expected for a match + + Returns the text which we think is the label, or None. + """ + + extents = self._getExtents(obj) + contents = self._getLineContents(obj) + content = [o for o in contents if o[0] == obj] + try: + index = contents.index(content[0]) + except IndexError: + index = len(contents) + + onLeft = contents[0:index] + start = 0 + for i in range(len(onLeft) - 1, -1, -1): + lObj, lStart, lEnd, lString = onLeft[i] + lExtents = self._getExtents(lObj) + if lExtents[0] > extents[0] or self._cannotLabel(lObj): + start = i + 1 + break + + onLeft = onLeft[start:] + if not (onLeft and onLeft[0]): + return None, [] + + lObj, start, end, string = onLeft[-1] + lExtents = self._getExtents(lObj, start, end) + distance = extents[0] - (lExtents[0] + lExtents[2]) + if 0 <= distance <= proximity: + strings = [content[3] for content in onLeft] + result = ''.join(strings).strip() + if result: + return result, [content[0] for content in onLeft] + + return None, [] + + def inferFromTextRight(self, obj, proximity=25): + """Attempt to infer the functional/displayed label of obj by + looking at the contents of the current line, which are to the + right of this object + + Arguments + - obj: the unlabeled widget + - proximity: pixels expected for a match + + Returns the text which we think is the label, or None. + """ + + if self._preventRight(obj): + return None, [] + + extents = self._getExtents(obj) + contents = self._getLineContents(obj) + content = [o for o in contents if o[0] == obj] + try: + index = contents.index(content[0]) + except IndexError: + index = len(contents) + + onRight = contents[min(len(contents), index+1):] + end = len(onRight) + for i, item in enumerate(onRight): + if self._cannotLabel(item[0]): + if not self._preferRight(obj): + return None, [] + end = i + 1 + break + + onRight = onRight[0:end] + if not (onRight and onRight[0]): + return None, [] + + rObj, start, end, string = onRight[0] + rExtents = self._getExtents(rObj, start, end) + distance = rExtents[0] - (extents[0] + extents[2]) + if distance <= proximity or self._preferRight(obj): + strings = [content[3] for content in onRight] + result = ''.join(strings).strip() + if result: + return result, [content[0] for content in onRight] + + return None, [] + + def inferFromTextAbove(self, obj, proximity=20): + """Attempt to infer the functional/displayed label of obj by + looking at the contents of the line above the line containing + the object obj. + + Arguments + - obj: the unlabeled widget + - proximity: pixels expected for a match + + Returns the text which we think is the label, or None. + """ + + thisLine = self._getLineContents(obj) + content = [o for o in thisLine if o[0] == obj] + try: + index = thisLine.index(content[0]) + except IndexError: + return None, [] + if index > 0: + return None, [] + + prevObj, prevOffset = self._script.utilities.previousContext( + thisLine[0][0], thisLine[0][1], True) + prevLine = self._getLineContents(prevObj, prevOffset) + if len(prevLine) != 1: + return None, [] + + prevObj, start, end, string = prevLine[0] + if self._cannotLabel(prevObj): + return None, [] + + if string.strip(): + x, y, width, height = self._getExtents(prevObj, start, end) + objX, objY, objWidth, objHeight = self._getExtents(obj) + distance = objY - (y + height) + if 0 <= distance <= proximity and x <= objX: + return string.strip(), [prevObj] + + return None, [] + + def inferFromTextBelow(self, obj, proximity=20): + """Attempt to infer the functional/displayed label of obj by + looking at the contents of the line above the line containing + the object obj. + + Arguments + - obj: the unlabeled widget + - proximity: pixels expected for a match + + Returns the text which we think is the label, or None. + """ + + if self._preventBelow(obj): + return None, [] + + thisLine = self._getLineContents(obj) + content = [o for o in thisLine if o[0] == obj] + try: + index = thisLine.index(content[0]) + except IndexError: + return None, [] + if index > 0: + return None, [] + + nextObj, nextOffset = self._script.utilities.nextContext( + thisLine[-1][0], thisLine[-1][2] - 1, True) + nextLine = self._getLineContents(nextObj, nextOffset) + if len(nextLine) != 1: + return None, [] + + nextObj, start, end, string = nextLine[0] + if self._cannotLabel(nextObj): + return None, [] + + if string.strip(): + x, y, width, height = self._getExtents(nextObj, start, end) + objX, objY, objWidth, objHeight = self._getExtents(obj) + distance = y - (objY + objHeight) + if 0 <= distance <= proximity: + return string.strip(), [nextObj] + + return None, [] + + def _isTable(self, obj): + if AXUtilities.is_table(obj): + return True + + return self._getTag(obj) == 'table' + + def _isRow(self, obj): + if AXUtilities.is_table_row(obj): + return True + + return self._getTag(obj) == 'tr' + + def _isCell(self, obj): + if AXUtilities.is_table_cell(obj): + return True + + return self._getTag(obj) in ['td', 'th'] + + def _getCellFromTable(self, table, rowindex, colindex): + if not AXObject.supports_table(table): + return None + + if rowindex < 0 or colindex < 0: + return None + + iface = table.queryTable() + if rowindex >= iface.nRows or colindex >= iface.nColumns: + return None + + return table.queryTable().getAccessibleAt(rowindex, colindex) + + def _getCellFromRow(self, row, colindex): + if 0 <= colindex < AXObject.get_child_count(row): + return row[colindex] + + return None + + def _getTag(self, obj): + attrs = self._script.utilities.objectAttributes(obj) + return attrs.get('tag') + + def inferFromTable(self, obj, proximityForRight=50): + """Attempt to infer the functional/displayed label of obj by looking + at the contents of the surrounding table cells. Note that this approach + assumes a simple table in which the widget is the sole occupant of its + cell. + + Arguments + - obj: the unlabeled widget + + Returns the text which we think is the label, or None. + """ + + cell = AXObject.find_ancestor(obj, self._isCell) + if not self._isSimpleObject(cell): + return None, [] + + parent = AXObject.get_parent(obj) + if cell not in [parent, AXObject.get_parent(parent)]: + return None, [] + + grid = AXObject.find_ancestor(cell, self._isTable) + if not grid: + return None, [] + + cellLeft = cellRight = cellAbove = cellBelow = None + gridrow = AXObject.find_ancestor(cell, self._isRow) + rowindex, colindex = self._script.utilities.coordinatesForCell(cell) + if colindex > -1: + cellLeft = self._getCellFromTable(grid, rowindex, colindex - 1) + cellRight = self._getCellFromTable(grid, rowindex, colindex + 1) + cellAbove = self._getCellFromTable(grid, rowindex - 1, colindex) + cellBelow = self._getCellFromTable(grid, rowindex + 1, colindex) + elif gridrow and AXObject.get_parent(cell) == gridrow: + cellindex = AXObject.get_index_in_parent(cell) + cellLeft = self._getCellFromRow(gridrow, cellindex - 1) + cellRight = self._getCellFromRow(gridrow, cellindex + 1) + rowindex = AXObject.get_index_in_parent(gridrow) + gridrowParent = AXObject.get_parent(gridrow) + if rowindex > 0: + rowAbove = AXObject.get_child(gridrowParent, rowindex - 1) + cellAbove = self._getCellFromRow(rowAbove, cellindex) + if rowindex + 1 < AXObject.get_child_count(grid): + rowBelow = AXObject.get_child(gridrowParent, rowindex + 1) + cellBelow = self._getCellFromRow(rowBelow, cellindex) + + if cellLeft and not self._preferRight(obj): + label, sources = self._createLabelFromContents(cellLeft) + if label: + return label.strip(), sources + + objX, objY, objWidth, objHeight = self._getExtents(obj) + + if cellRight and not self._preventRight(obj): + x, y, width, height = self._getExtents(cellRight) + distance = x - (objX + objWidth) + if distance <= proximityForRight or self._preferRight(obj): + label, sources = self._createLabelFromContents(cellRight) + if label: + return label.strip(), sources + + labelAbove = labelBelow = None + if cellAbove: + labelAbove, sourcesAbove = self._createLabelFromContents(cellAbove) + if labelAbove and self._preferTop(obj): + return labelAbove.strip(), sourcesAbove + + if cellBelow and not self._preventBelow(obj): + labelBelow, sourcesBelow = self._createLabelFromContents(cellBelow) + + if labelAbove and labelBelow: + aboveX, aboveY, aboveWidth, aboveHeight = self._getExtents(cellAbove) + belowX, belowY, belowWidth, belowHeight = self._getExtents(cellBelow) + dAbove = objY - (aboveY + aboveHeight) + dBelow = belowY - (objY + objHeight) + if dAbove <= dBelow: + return labelAbove.strip(), sourcesAbove + return labelBelow.strip(), sourcesBelow + + if labelAbove: + return labelAbove.strip(), sourcesAbove + if labelBelow: + return labelBelow.strip(), sourcesBelow + + # None of the cells immediately surrounding this cell seem to be serving + # as a functional label. Therefore, see if this table looks like a grid + # of widgets with the functional labels in the first row. + + try: + table = grid.queryTable() + except NotImplementedError: + return None, [] + + firstRow = [table.getAccessibleAt(0, i) for i in range(table.nColumns)] + if not firstRow or list(filter(self._isWidget, firstRow)): + return None, [] + + if colindex < 0: + return None, [] + + def isMatch(x): + if not AXObject.get_child_count(x): + return False + return not AXUtilities.have_same_role(AXObject.get_child(x, 0), obj) + + cells = [table.getAccessibleAt(i, colindex) for i in range(1, table.nRows)] + if list(filter(isMatch, cells)): + return None, [] + + label, sources = self._createLabelFromContents(firstRow[colindex]) + if label: + return label.strip(), sources + + return None, [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/laptop_keyboardmap.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/laptop_keyboardmap.py new file mode 100644 index 0000000..c4bcfda --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/laptop_keyboardmap.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" A list of common keybindings and unbound keys + pulled out from default.py: __getLaptopBindings() + with the goal of being more readable and less monolithic. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs, Mesar Hameed." +__license__ = "LGPL" + +from . import keybindings + +# Storing values +defaultModifierMask = keybindings.defaultModifierMask +CTHULHU_MODIFIER_MASK = keybindings.CTHULHU_MODIFIER_MASK +NO_MODIFIER_MASK = keybindings.NO_MODIFIER_MASK +CTHULHU_SHIFT_MODIFIER_MASK = keybindings.CTHULHU_SHIFT_MODIFIER_MASK +CTHULHU_CTRL_MODIFIER_MASK = keybindings.CTHULHU_CTRL_MODIFIER_MASK + +keymap = ( + + ("9", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "routePointerToItemHandler"), + + # We want the user to be able to combine modifiers with the + # mouse click (e.g. to Shift+Click and select), therefore we + # do not "care" about the modifiers (other than the Cthulhu + # modifier). + # + + ("7", CTHULHU_MODIFIER_MASK, CTHULHU_MODIFIER_MASK, + "leftClickReviewItemHandler"), + + ("8", CTHULHU_MODIFIER_MASK, CTHULHU_MODIFIER_MASK, + "rightClickReviewItemHandler"), + + ("semicolon", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "sayAllHandler", 1), + + ("bracketleft", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "findHandler"), + + ("bracketright", defaultModifierMask, CTHULHU_MODIFIER_MASK, + "findNextHandler"), + + ("bracketright", defaultModifierMask, CTHULHU_CTRL_MODIFIER_MASK, + "findPreviousHandler"), + +) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/learn_mode_presenter.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/learn_mode_presenter.py new file mode 100644 index 0000000..6ff3fd3 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/learn_mode_presenter.py @@ -0,0 +1,386 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for learn mode""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2016-2023 Igalia, S.L." +__license__ = "LGPL" + +import gi + +gi.require_version("Atspi", "2.0") +gi.require_version("Gdk", "3.0") +gi.require_version("Gtk", "3.0") +from gi.repository import Atspi +from gi.repository import Gdk +from gi.repository import GObject +from gi.repository import Gtk + +from . import cmdnames +from . import debug +from . import guilabels +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu_state +from . import settings +from . import settings_manager +from .ax_object import AXObject + + +class LearnModePresenter: + """Provides implementation of learn mode""" + + def __init__(self): + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + self._is_active = False + self._gui = None + + def is_active(self): + """Returns True if we're in learn mode""" + + return self._is_active + + def get_bindings(self): + """Returns the learn-mode-presenter keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the learn-mode-presenter handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the learn-mode-presenter input event handlers.""" + + handlers = {} + + handlers["enterLearnModeHandler"] = \ + input_event.InputEventHandler( + self.start, + cmdnames.ENTER_LEARN_MODE) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the learn-mode-presenter key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "h", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("enterLearnModeHandler"))) + + return bindings + + def start(self, script=None, event=None): + """Starts learn mode.""" + + if self._is_active: + msg = "LEARN MODE PRESENTER: Start called when already active" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if script is None: + script = cthulhu_state.activeScript + + if script is not None: + script.presentMessage(messages.VERSION) + script.speakMessage(messages.LEARN_MODE_START_SPEECH) + script.displayBrailleMessage(messages.LEARN_MODE_START_BRAILLE) + + if cthulhu_state.device is not None: + msg = "LEARN MODE PRESENTER: Grabbing keyboard" + debug.printMessage(debug.LEVEL_INFO, msg, True) + Atspi.Device.grab_keyboard(cthulhu_state.device) + + msg = "LEARN MODE PRESENTER: Is now active" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._is_active = True + return True + + def quit(self, script=None, event=None): + """Quits learn mode.""" + + if not self._is_active: + msg = "LEARN MODE PRESENTER: Quit called when already inactive" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if script is None: + script = cthulhu_state.activeScript + + if script is not None: + script.presentMessage(messages.LEARN_MODE_STOP) + + if cthulhu_state.device is not None: + msg = "LEARN MODE PRESENTER: Ungrabbing keyboard" + debug.printMessage(debug.LEVEL_INFO, msg, True) + Atspi.Device.ungrab_keyboard(cthulhu_state.device) + + msg = "LEARN MODE PRESENTER: Is now inactive" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._is_active = False + return True + + def handle_event(self, event=None): + """Handles the event if learn mode is active.""" + + if not self._is_active: + return False + + if not isinstance(event, input_event.KeyboardEvent): + return False + + cthulhu_state.activeScript.speakKeyEvent(event) + if event.isPrintableKey() and event.getClickCount() == 2 \ + and event.getHandler() is None: + cthulhu_state.activeScript.phoneticSpellCurrentItem(event.event_string) + + if event.event_string == "Escape": + self.quit(script=None, event=event) + return True + + if event.event_string == "F1" and not event.modifiers: + self.show_help(cthulhu_state.activeScript, event) + return True + + if event.event_string in ["F2", "F3"] and not event.modifiers: + self.list_cthulhu_shortcuts(cthulhu_state.activeScript, event) + return True + + self.present_command(event) + return True + + def present_command(self, event=None): + """Presents the command bound to event.""" + + if not isinstance(event, input_event.KeyboardEvent): + return True + + handler = event.getHandler() + if handler is None: + debug.printMessage(debug.LEVEL_INFO, "LEARN MODE PRESENTER: No handler found for event", True) + return True + + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Handler found: {handler}", True) + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Handler description: {getattr(handler, 'description', 'No description')}", True) + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Handler learnModeEnabled: {getattr(handler, 'learnModeEnabled', 'No learnModeEnabled')}", True) + + if handler.learnModeEnabled and handler.description: + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Presenting message: {handler.description}", True) + cthulhu_state.activeScript.presentMessage(handler.description) + else: + debug.printMessage(debug.LEVEL_INFO, "LEARN MODE PRESENTER: Handler missing required properties for learn mode", True) + + return True + + def list_cthulhu_shortcuts(self, script, event=None): + """Shows a simple gui listing Cthulhu's bound commands.""" + + if event is None: + event = cthulhu_state.lastNonModifierKeyEvent + + layout = settings_manager.getManager().getSetting("keyboardLayout") + is_desktop = layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP + + items = 0 + bindings = {} + if event is None or event.event_string == "F2": + bound = script.getLearnModePresenter().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_LEARN_MODE] = bound + items += len(bound) + + bound = script.getDefaultKeyBindings().getBoundBindings() + bindings[guilabels.KB_GROUP_DEFAULT] = bound + items += len(bound) + + bound = script.getWhereAmIPresenter().get_bindings(is_desktop).getBoundBindings() + bindings[guilabels.KB_GROUP_WHERE_AM_I] = bound + items += len(bound) + + bound = script.getSpeechAndVerbosityManager().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_SPEECH_VERBOSITY] = bound + items += len(bound) + + bound = script.getFlatReviewPresenter().get_bindings(is_desktop).getBoundBindings() + bindings[guilabels.KB_GROUP_FLAT_REVIEW] = bound + items += len(bound) + + bound = script.getObjectNavigator().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_OBJECT_NAVIGATION] = bound + items += len(bound) + + bound = script.getDateAndTimePresenter().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_DATE_AND_TIME] = bound + items += len(bound) + + bound = script.getNotificationPresenter().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_NOTIFICATIONS] = bound + items += len(bound) + + bound = script.getBookmarks().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_BOOKMARKS] = bound + items += len(bound) + + bound = script.getMouseReviewer().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_MOUSE_REVIEW] = bound + items += len(bound) + + bound = script.getActionPresenter().get_bindings().getBoundBindings() + bindings[guilabels.KB_GROUP_ACTIONS] = bound + items += len(bound) + + # Add plugin keybindings + try: + debug.printMessage(debug.LEVEL_INFO, "LEARN MODE PRESENTER: Getting plugin keybindings", True) + plugin_bindings = script.getPluginKeyBindings() + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Got plugin bindings object: {plugin_bindings}", True) + bound = plugin_bindings.getBoundBindings() + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Got {len(bound)} bound plugin keybindings", True) + if bound: + bindings["Plugins"] = bound + items += len(bound) + debug.printMessage(debug.LEVEL_INFO, f"LEARN MODE PRESENTER: Added {len(bound)} plugin keybindings to learn mode", True) + except Exception as e: + msg = f"LEARN MODE PRESENTER: Could not get plugin keybindings: {e}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + import traceback + debug.printMessage(debug.LEVEL_INFO, traceback.format_exc(), True) + + title = messages.shortcutsFoundCthulhu(items) + else: + app_name = AXObject.get_name(script.app) or messages.APPLICATION_NO_NAME + bound = script.getAppKeyBindings().getBoundBindings() + bound.extend(script.getToolkitKeyBindings().getBoundBindings()) + if bound: + bindings[app_name] = bound + title = messages.shortcutsFoundApp(len(bound), app_name) + + if not bindings: + script.presentMessage(title) + return True + + self.quit(script, event) + column_headers = [guilabels.KB_HEADER_FUNCTION, guilabels.KB_HEADER_KEY_BINDING] + self._gui = CommandListGUI(script, title, column_headers, bindings) + self._gui.show_gui() + return True + + def show_help(self, script=None, event=None, page=""): + """Displays Cthulhu's documentation.""" + + self.quit(script, event) + uri = "help:cthulhu" + if page: + uri += f"/{page}" + Gtk.show_uri(Gdk.Screen.get_default(), uri, Gtk.get_current_event_time()) + return True + +class CommandListGUI: + """Shows a list of commands and their bindings.""" + + def __init__(self, script, title, column_headers, bindings_dict): + self._script = script + self._model = None + self._gui = self._create_dialog(title, column_headers, bindings_dict) + + def _create_dialog(self, title, column_headers, bindings_dict): + """Creates the commands-list dialog.""" + + dialog = Gtk.Dialog(title, + None, + Gtk.DialogFlags.MODAL, + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) + dialog.set_default_size(1000, 800) + + grid = Gtk.Grid() + content_area = dialog.get_content_area() + content_area.add(grid) + + scrolled_window = Gtk.ScrolledWindow() + grid.add(scrolled_window) + + tree = Gtk.TreeView() + tree.set_hexpand(True) + tree.set_vexpand(True) + scrolled_window.add(tree) + + cols = len(column_headers) * [GObject.TYPE_STRING] + for i, header in enumerate(column_headers): + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(header, cell, text=i) + tree.append_column(column) + if header: + column.set_sort_column_id(i) + + self._model = Gtk.TreeStore(*cols) + + for group, bindings in bindings_dict.items(): + if not bindings: + continue + group_iter = self._model.append(None, [group, ""]) + for binding in bindings: + self._model.append(group_iter, [binding.handler.description, binding.asString()]) + + tree.set_model(self._model) + tree.expand_all() + dialog.connect("response", self.on_response) + return dialog + + def on_response(self, dialog, response): + """Handler for the 'response' signal.""" + + if response == Gtk.ResponseType.CLOSE: + self._gui.destroy() + return + + def show_gui(self): + """Shows the dialog.""" + + self._gui.show_all() + time_stamp = cthulhu_state.lastInputEvent.timestamp + if time_stamp == 0: + time_stamp = Gtk.get_current_event_time() + self._gui.present_with_time(time_stamp) + + +_presenter = None +def getPresenter(): + """Returns the Learn Mode Presenter""" + + global _presenter + if _presenter is None: + _presenter = LearnModePresenter() + return _presenter diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/liveregions.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/liveregions.py new file mode 100644 index 0000000..93a9c3a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/liveregions.py @@ -0,0 +1,608 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import bisect +import copy +import time +from gi.repository import GLib + +from . import cmdnames +from . import chnames +from . import debug +from . import keybindings +from . import messages +from . import input_event +from . import cthulhu_state +from . import settings_manager +from .ax_collection import AXCollection +from .ax_object import AXObject + +_settingsManager = settings_manager.getManager() + +# define 'live' property types +LIVE_OFF = -1 +LIVE_NONE = 0 +LIVE_POLITE = 1 +LIVE_ASSERTIVE = 2 +LIVE_RUDE = 3 + +# Seconds a message is held in the queue before it is discarded +MSG_KEEPALIVE_TIME = 45 # in seconds + +# The number of messages that are cached and can later be reviewed via +# LiveRegionManager.reviewLiveAnnouncement. +CACHE_SIZE = 9 # corresponds to one of nine key bindings + +class PriorityQueue: + """ This class represents a thread **UNSAFE** priority queue where priority + is determined by the given integer priority. The entries are also + maintained in chronological order. + + TODO: experiment with Queue.Queue to make thread safe + """ + def __init__(self): + self.queue = [] + + def enqueue(self, data, priority, obj): + """ Add a new element to the queue according to 1) priority and + 2) timestamp. """ + bisect.insort_left(self.queue, (priority, time.time(), data, obj)) + + def dequeue(self): + """get the highest priority element from the queue. """ + return self.queue.pop(0) + + def clear(self): + """ Clear the queue """ + self.queue = [] + + def purgeByKeepAlive(self): + """ Purge items from the queue that are older than the keepalive time """ + currenttime = time.time() + + def myfilter(item): + return item and item[1] + MSG_KEEPALIVE_TIME > currenttime + + self.queue = list(filter(myfilter, self.queue)) + + def purgeByPriority(self, priority): + """ Purge items from the queue that have a lower than or equal priority + than the given argument """ + + def myfilter(item): + return item and item[0] > priority + + self.queue = list(filter(myfilter, self.queue)) + + def __len__(self): + """ Return the length of the queue """ + return len(self.queue) + + +class LiveRegionManager: + def __init__(self, script): + self._script = script + # message priority queue + self.msg_queue = PriorityQueue() + + self.inputEventHandlers = self._getInputEventHandlers() + self.keyBindings = self._getKeyBindings() + + # This is temporary. + self.functions = [self.advancePoliteness, + self.setLivePolitenessOff, + self.toggleMonitoring, + self.reviewLiveAnnouncement] + + # Message cache. Used to store up to 9 previous messages so user can + # review if desired. + self.msg_cache = [] + + # User overrides for politeness settings. + self._politenessOverrides = None + self._restoreOverrides = None + + # last live obj to be announced + self.lastliveobj = None + + # Used to track whether a user wants to monitor all live regions + # Not to be confused with the global Gecko.liveRegionsOn which + # completely turns off live region support. This one is based on + # a user control by changing politeness levels to LIVE_OFF or back + # to the bookmark or markup politeness value. + self.monitoring = True + + # Set up politeness level overrides and subscribe to bookmarks + # for load and save user events. + # We are initialized after bookmarks so call the load handler once + # to get initialized. + # + self.bookmarkLoadHandler() + script.bookmarks.addSaveObserver(self.bookmarkSaveHandler) + script.bookmarks.addLoadObserver(self.bookmarkLoadHandler) + + def _getInputEventHandlers(self): + handlers = {} + + handlers["advanceLivePoliteness"] = \ + input_event.InputEventHandler( + self.advancePoliteness, + cmdnames.LIVE_REGIONS_ADVANCE_POLITENESS) + + handlers["setLivePolitenessOff"] = \ + input_event.InputEventHandler( + self.setLivePolitenessOff, + cmdnames.LIVE_REGIONS_SET_POLITENESS_OFF) + + handlers["monitorLiveRegions"] = \ + input_event.InputEventHandler( + self.toggleMonitoring, + cmdnames.LIVE_REGIONS_MONITOR) + + handlers["reviewLiveAnnouncement"] = \ + input_event.InputEventHandler( + self.reviewLiveAnnouncement, + cmdnames.LIVE_REGIONS_REVIEW) + + return handlers + + def _getKeyBindings(self): + keyBindings = keybindings.KeyBindings() + + keyBindings.add( + keybindings.KeyBinding( + "backslash", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self.inputEventHandlers.get("advanceLivePoliteness"))) + + keyBindings.add( + keybindings.KeyBinding( + "backslash", + keybindings.defaultModifierMask, + keybindings.SHIFT_MODIFIER_MASK, + self.inputEventHandlers.get("setLivePolitenessOff"))) + + keyBindings.add( + keybindings.KeyBinding( + "backslash", + keybindings.defaultModifierMask, + keybindings.CTHULHU_SHIFT_MODIFIER_MASK, + self.inputEventHandlers.get("monitorLiveRegions"))) + + for key in ["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"]: + keyBindings.add( + keybindings.KeyBinding( + key, + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers.get("reviewLiveAnnouncement"))) + + return keyBindings + + def reset(self): + # First we will purge our politeness override dictionary of LIVE_NONE + # objects that are not registered for this page + newpoliteness = {} + currenturi = self._script.bookmarks.getURIKey() + for key, value in self._politenessOverrides.items(): + if key[0] == currenturi or value != LIVE_NONE: + newpoliteness[key] = value + self._politenessOverrides = newpoliteness + + def bookmarkSaveHandler(self): + """Bookmark save callback""" + self._script.bookmarks.saveBookmarksToDisk(self._politenessOverrides, + filename='politeness') + + def bookmarkLoadHandler(self): + """Bookmark load callback""" + # readBookmarksFromDisk() returns None on error. Just initialize to an + # empty dictionary if this is the case. + self._politenessOverrides = \ + self._script.bookmarks.readBookmarksFromDisk(filename='politeness') \ + or {} + + def handleEvent(self, event): + """Main live region event handler""" + politeness = self._getLiveType(event.source) + if politeness == LIVE_OFF: + return + if politeness == LIVE_NONE: + # All the 'registered' LIVE_NONE objects will be set to off + # if not monitoring. We will ignore LIVE_NONE objects that + # arrive after the user switches off monitoring. + if not self.monitoring: + return + elif politeness == LIVE_POLITE: + # Nothing to do for now + pass + elif politeness == LIVE_ASSERTIVE: + self.msg_queue.purgeByPriority(LIVE_POLITE) + elif politeness == LIVE_RUDE: + self.msg_queue.purgeByPriority(LIVE_ASSERTIVE) + + message = self._getMessage(event) + if message: + if len(self.msg_queue) == 0: + GLib.timeout_add(100, self.pumpMessages) + self.msg_queue.enqueue(message, politeness, event.source) + + def pumpMessages(self): + """ Main gobject callback for live region support. Handles both + purging the message queue and outputting any queued messages that + were queued up in the handleEvent() method. + """ + + if len(self.msg_queue) > 0: + debug.printMessage(debug.eventDebugLevel, "\nvvvvv PRESENT LIVE REGION MESSAGE vvvvv") + self.msg_queue.purgeByKeepAlive() + politeness, timestamp, message, obj = self.msg_queue.dequeue() + # Form output message. No need to repeat labels and content. + # TODO: really needs to be tested in real life cases. Perhaps + # a verbosity setting? + if message['labels'] == message['content']: + utts = message['content'] + else: + utts = message['labels'] + message['content'] + + if self.monitoring: + self._script.presentMessage(utts) + else: + msg = "INFO: Not presenting message because monitoring is off" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # set the last live obj to be announced + self.lastliveobj = obj + + # cache our message + self._cacheMessage(utts) + + # We still want to maintain our queue if we are not monitoring + if not self.monitoring: + self.msg_queue.purgeByKeepAlive() + + msg = f'LIVE REGIONS: messages in queue: {len(self.msg_queue)}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + debug.printMessage(debug.eventDebugLevel, "^^^^^ PRESENT LIVE REGION MESSAGE ^^^^^\n") + + # See you again soon, stay in event loop if we still have messages. + return len(self.msg_queue) > 0 + + def getLiveNoneObjects(self): + """Return the live objects that are registered and have a politeness + of LIVE_NONE. """ + retval = [] + currenturi = self._script.bookmarks.getURIKey() + for uri, objectid in self._politenessOverrides: + if uri == currenturi and isinstance(objectid, tuple): + retval.append(self._script.bookmarks.pathToObj(objectid)) + return retval + + def advancePoliteness(self, script, inputEvent): + """Advance the politeness level of the given object""" + + if not _settingsManager.getSetting('inferLiveRegions'): + self._script.presentMessage(messages.LIVE_REGIONS_OFF) + return + + obj = cthulhu_state.locusOfFocus + objectid = self._getObjectId(obj) + uri = self._script.bookmarks.getURIKey() + + try: + # The current priority is either a previous override or the + # live property. If an exception is thrown, an override for + # this object has never occurred and the object does not have + # live markup. In either case, set the override to LIVE_NONE. + cur_priority = self._politenessOverrides[(uri, objectid)] + except KeyError: + cur_priority = self._liveStringToType(obj) + + if cur_priority == LIVE_OFF or cur_priority == LIVE_NONE: + self._politenessOverrides[(uri, objectid)] = LIVE_POLITE + self._script.presentMessage(messages.LIVE_REGIONS_LEVEL_POLITE) + elif cur_priority == LIVE_POLITE: + self._politenessOverrides[(uri, objectid)] = LIVE_ASSERTIVE + self._script.presentMessage(messages.LIVE_REGIONS_LEVEL_ASSERTIVE) + elif cur_priority == LIVE_ASSERTIVE: + self._politenessOverrides[(uri, objectid)] = LIVE_RUDE + self._script.presentMessage(messages.LIVE_REGIONS_LEVEL_RUDE) + elif cur_priority == LIVE_RUDE: + self._politenessOverrides[(uri, objectid)] = LIVE_OFF + self._script.presentMessage(messages.LIVE_REGIONS_LEVEL_OFF) + + + def goLastLiveRegion(self): + """Move the caret to the last announced live region and speak the + contents of that object""" + if self.lastliveobj: + self._script.utilities.setCaretPosition(self.lastliveobj, 0) + self._script.speakContents(self._script.utilities.getObjectContentsAtOffset( + self.lastliveobj, 0)) + + def reviewLiveAnnouncement(self, script, inputEvent): + """Speak the given number cached message""" + + msgnum = int(inputEvent.event_string[1:]) + if not _settingsManager.getSetting('inferLiveRegions'): + self._script.presentMessage(messages.LIVE_REGIONS_OFF) + return + + if msgnum > len(self.msg_cache): + self._script.presentMessage(messages.LIVE_REGIONS_NO_MESSAGE) + else: + self._script.presentMessage(self.msg_cache[-msgnum]) + + def setLivePolitenessOff(self, script, inputEvent): + """User toggle to set all live regions to LIVE_OFF or back to their + original politeness.""" + + if not _settingsManager.getSetting('inferLiveRegions'): + self._script.presentMessage(messages.LIVE_REGIONS_OFF) + return + + # start at the document frame + docframe = self._script.utilities.documentFrame() + # get the URI of the page. It is used as a partial key. + uri = self._script.bookmarks.getURIKey() + + # The user is currently monitoring live regions but now wants to + # change all live region politeness on page to LIVE_OFF + if self.monitoring: + self._script.presentMessage(messages.LIVE_REGIONS_ALL_OFF) + self.msg_queue.clear() + + # First we'll save off a copy for quick restoration + self._restoreOverrides = copy.copy(self._politenessOverrides) + + # Set all politeness overrides to LIVE_OFF. + for override in self._politenessOverrides.keys(): + self._politenessOverrides[override] = LIVE_OFF + + # look through all the objects on the page and set/add to + # politeness overrides. This only adds live regions with good + # markup. + matches = self.getAllLiveRegions(docframe) + for match in matches: + objectid = self._getObjectId(match) + self._politenessOverrides[(uri, objectid)] = LIVE_OFF + + # Toggle our flag + self.monitoring = False + + # The user wants to restore politeness levels + else: + for key, value in self._restoreOverrides.items(): + self._politenessOverrides[key] = value + self._script.presentMessage(messages.LIVE_REGIONS_ALL_RESTORED) + # Toggle our flag + self.monitoring = True + + def getAllLiveRegions(self, document): + attrs = [] + levels = ["off", "polite", "assertive"] + for level in levels: + attrs.append('container-live:' + level) + + rule = AXCollection.create_match_rule(attributes=attrs) + result = AXCollection.get_all_matches(document, rule) + + msg = f'LIVE REGIONS: {len(result)} regions found' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return result + + def generateLiveRegionDescription(self, obj, **args): + """Used in conjunction with whereAmI to output description and + politeness of the given live region object""" + objectid = self._getObjectId(obj) + uri = self._script.bookmarks.getURIKey() + + results = [] + + # get the description if there is one. + relation = AXObject.get_relation(obj, Atspi.RelationType.DESCRIBED_BY) + if relation: + targetobj = relation.getTarget(0) + try: + # We will add on descriptions if they don't duplicate + # what's already in the object's description. + # See http://bugzilla.gnome.org/show_bug.cgi?id=568467 + # for more information. + # + description = targetobj.queryText().getText(0, -1) + if description.strip() != AXObject.get_description(obj).strip(): + results.append(description) + except NotImplementedError: + pass + + # get the politeness level as a string + try: + livepriority = self._politenessOverrides[(uri, objectid)] + liveprioritystr = self._liveTypeToString(livepriority) + except KeyError: + liveprioritystr = 'none' + + # We will only output useful information + # + if results or liveprioritystr != 'none': + results.append(messages.LIVE_REGIONS_LEVEL % liveprioritystr) + + return results + + def _findContainer(self, obj): + def isContainer(x): + return self._getAttrDictionary(x).get('atomic') + + if isContainer(obj): + return obj + + return AXObject.find_ancestor(obj, isContainer) + + def _getMessage(self, event): + """Gets the message associated with a given live event.""" + attrs = self._getAttrDictionary(event.source) + content = "" + labels = "" + + # A message is divided into two parts: labels and content. We + # will first try to get the content. If there is None, + # assume it is an invalid message and return None + if event.type.startswith('object:children-changed:add'): + if attrs.get('container-atomic') == 'true': + content = self._script.utilities.expandEOCs(event.source) + else: + content = self._script.utilities.expandEOCs(event.any_data) + + elif event.type.startswith('object:text-changed:insert'): + if attrs.get('container-atomic') != 'true': + if "\ufffc" not in event.any_data: + content = event.any_data + else: + content = self._script.utilities.expandEOCs( + event.source, event.detail1, event.detail1 + event.detail2) + else: + container = self._findContainer(event.source) + content = self._script.utilities.expandEOCs(container) + + if not content: + return None + + content = content.strip() + if len(content) == 1: + content = chnames.getCharacterName(content) + + # Proper live regions typically come with proper aria labels. These + # labels are typically exposed as names. Failing that, descriptions. + # Looking for actual labels seems a non-performant waste of time. + name = (AXObject.get_name(event.source) or AXObject.get_description(event.source)).strip() + if name and name != content: + labels = name + + # instantly send out notify messages + if attrs.get('channel') == 'notify': + utts = labels + content + self._script.presentationInterrupt() + self._script.presentMessage(utts) + return None + + return {'content':[content], 'labels':[labels]} + + def flushMessages(self): + self.msg_queue.clear() + + def _cacheMessage(self, utts): + """Cache a message in our cache list of length CACHE_SIZE""" + self.msg_cache.append(utts) + if len(self.msg_cache) > CACHE_SIZE: + self.msg_cache.pop(0) + + def _getLiveType(self, obj): + """Returns the live politeness setting for a given object. Also, + registers LIVE_NONE objects in politeness overrides when monitoring.""" + objectid = self._getObjectId(obj) + uri = self._script.bookmarks.getURIKey() + if (uri, objectid) in self._politenessOverrides: + # look to see if there is a user politeness override + return self._politenessOverrides[(uri, objectid)] + else: + livetype = self._liveStringToType(obj) + # We'll save off a reference to LIVE_NONE if we are monitoring + # to give the user a chance to change the politeness level. It + # is done here for performance sake (objectid, uri are expensive) + if livetype == LIVE_NONE and self.monitoring: + self._politenessOverrides[(uri, objectid)] = livetype + return livetype + + def _getObjectId(self, obj): + """Returns the HTML 'id' or a path to the object is an HTML id is + unavailable""" + attrs = self._getAttrDictionary(obj) + if attrs is None: + return self._getPath(obj) + try: + return attrs['id'] + except KeyError: + return self._getPath(obj) + + def _liveStringToType(self, obj, attributes=None): + """Returns the politeness enum for a given object""" + attrs = attributes or self._getAttrDictionary(obj) + try: + if attrs['container-live'] == 'off': + return LIVE_OFF + elif attrs['container-live'] == 'polite': + return LIVE_POLITE + elif attrs['container-live'] == 'assertive': + return LIVE_ASSERTIVE + elif attrs['container-live'] == 'rude': + return LIVE_RUDE + else: + return LIVE_NONE + except KeyError: + return LIVE_NONE + + def _liveTypeToString(self, politeness): + """Returns the politeness level as a string given a politeness enum""" + if politeness == LIVE_OFF: + return 'off' + elif politeness == LIVE_POLITE: + return 'polite' + elif politeness == LIVE_ASSERTIVE: + return 'assertive' + elif politeness == LIVE_RUDE: + return 'rude' + elif politeness == LIVE_NONE: + return 'none' + else: + return 'unknown' + + def _getAttrDictionary(self, obj): + return self._script.utilities.objectAttributes(obj) + + def _getPath(self, obj): + """ Returns, as a tuple of integers, the path from the given object + to the document frame.""" + docframe = self._script.utilities.documentFrame() + path = [] + while True: + if obj == docframe or AXObject.get_parent(obj) is None: + path.reverse() + return tuple(path) + path.append(AXObject.get_index_in_parent(obj)) + obj = AXObject.get_parent(obj) + + def toggleMonitoring(self, script, inputEvent): + if not _settingsManager.getSetting('inferLiveRegions'): + _settingsManager.setSetting('inferLiveRegions', True) + self._script.presentMessage(messages.LIVE_REGIONS_MONITORING_ON) + else: + _settingsManager.setSetting('inferLiveRegions', False) + self.flushMessages() + self._script.presentMessage(messages.LIVE_REGIONS_MONITORING_OFF) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/logger.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/logger.py new file mode 100644 index 0000000..74d3286 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/logger.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Output logger for regression testing.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2012 Igalia, S.L." +__license__ = "LGPL" + +import io +import logging + +class Logger: + + def __init__(self): + self._logs = {} + + def getLogNames(self): + return self._logs.keys() + + def newLog(self, name, level=logging.INFO): + log = logging.getLogger(name) + log.setLevel(level) + + handler = logging.StreamHandler(io.StringIO()) + handler.setFormatter(logging.Formatter('%(message)s')) + log.addHandler(handler) + + self._logs[name] = handler.stream + return log + + def clearLog(self, name): + stream = self._logs.get(name) + if stream: + stream.truncate(0) + stream.seek(0) + + def getLogContent(self, name): + stream = self._logs.get(name) + if stream: + return stream.getvalue() + + return "" + + def shutdown(self): + for name in self._logs.keys(): + stream = self._logs.get(name) + stream.close() + +_logger = Logger() + +def getLogger(): + return _logger diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mathsymbols.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mathsymbols.py new file mode 100644 index 0000000..edec26b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mathsymbols.py @@ -0,0 +1,2332 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import re +import unicodedata + +from .cthulhu_i18n import C_ + +fallbackOnUnicodeData = False + +SPEAK_NEVER = 1 +SPEAK_ALWAYS = 2 +SPEAK_FOR_CHARS = 3 +speakStyle = SPEAK_ALWAYS + +_all = {} +_alnum = {} +_arrows = {} +_operators = {} +_shapes = {} +_combining = {} + +# Note that the following are to help us identify what is likely a math symbol +# (as opposed to one serving the function of an image in "This way up.") +_arrows.update(dict.fromkeys(map(chr, range(0x2190, 0x2200)))) +_arrows.update(dict.fromkeys(map(chr, range(0x2750, 0x2800)))) +_arrows.update(dict.fromkeys(map(chr, range(0x2b30, 0x2b50)))) +_operators.update(dict.fromkeys(map(chr, range(0x2220, 0x2300)))) +_operators.update(dict.fromkeys(map(chr, range(0x2a00, 0x2b00)))) +_shapes.update(dict.fromkeys(map(chr, range(0x25a0, 0x2600)))) + +# Unicode has a huge number of individual symbols to include styles, such as +# bold, italic, double-struck, etc. These are so far not supported by speech +# synthesizers. So we'll maintain a dictionary of equivalent symbols which +# speech synthesizers should know along with lists of the various styles. +_alnum['\u2102'] = 'C' +_alnum['\u210a'] = 'g' +_alnum['\u210b'] = 'H' +_alnum['\u210c'] = 'H' +_alnum['\u210d'] = 'H' +_alnum['\u210e'] = 'h' +_alnum['\u2110'] = 'I' +_alnum['\u2111'] = 'I' +_alnum['\u2112'] = 'L' +_alnum['\u2113'] = 'l' +_alnum['\u2115'] = 'N' +_alnum['\u2119'] = 'P' +_alnum['\u211a'] = 'Q' +_alnum['\u211b'] = 'R' +_alnum['\u211c'] = 'R' +_alnum['\u211d'] = 'R' +_alnum['\u2124'] = 'Z' +_alnum['\u2128'] = 'Z' +_alnum['\u212c'] = 'B' +_alnum['\u212d'] = 'C' +_alnum['\u212f'] = 'e' +_alnum['\u2130'] = 'E' +_alnum['\u2131'] = 'F' +_alnum['\u2133'] = 'M' +_alnum['\u2134'] = 'o' +_alnum['\U0001d400'] = 'A' +_alnum['\U0001d401'] = 'B' +_alnum['\U0001d402'] = 'C' +_alnum['\U0001d403'] = 'D' +_alnum['\U0001d404'] = 'E' +_alnum['\U0001d405'] = 'F' +_alnum['\U0001d406'] = 'G' +_alnum['\U0001d407'] = 'H' +_alnum['\U0001d408'] = 'I' +_alnum['\U0001d409'] = 'J' +_alnum['\U0001d40a'] = 'K' +_alnum['\U0001d40b'] = 'L' +_alnum['\U0001d40c'] = 'M' +_alnum['\U0001d40d'] = 'N' +_alnum['\U0001d40e'] = 'O' +_alnum['\U0001d40f'] = 'P' +_alnum['\U0001d410'] = 'Q' +_alnum['\U0001d411'] = 'R' +_alnum['\U0001d412'] = 'S' +_alnum['\U0001d413'] = 'T' +_alnum['\U0001d414'] = 'U' +_alnum['\U0001d415'] = 'V' +_alnum['\U0001d416'] = 'W' +_alnum['\U0001d417'] = 'X' +_alnum['\U0001d418'] = 'Y' +_alnum['\U0001d419'] = 'Z' +_alnum['\U0001d41a'] = 'a' +_alnum['\U0001d41b'] = 'b' +_alnum['\U0001d41c'] = 'c' +_alnum['\U0001d41d'] = 'd' +_alnum['\U0001d41e'] = 'e' +_alnum['\U0001d41f'] = 'f' +_alnum['\U0001d420'] = 'g' +_alnum['\U0001d421'] = 'h' +_alnum['\U0001d422'] = 'i' +_alnum['\U0001d423'] = 'j' +_alnum['\U0001d424'] = 'k' +_alnum['\U0001d425'] = 'l' +_alnum['\U0001d426'] = 'm' +_alnum['\U0001d427'] = 'n' +_alnum['\U0001d428'] = 'o' +_alnum['\U0001d429'] = 'p' +_alnum['\U0001d42a'] = 'q' +_alnum['\U0001d42b'] = 'r' +_alnum['\U0001d42c'] = 's' +_alnum['\U0001d42d'] = 't' +_alnum['\U0001d42e'] = 'u' +_alnum['\U0001d42f'] = 'v' +_alnum['\U0001d430'] = 'w' +_alnum['\U0001d431'] = 'x' +_alnum['\U0001d432'] = 'y' +_alnum['\U0001d433'] = 'z' +_alnum['\U0001d434'] = 'A' +_alnum['\U0001d435'] = 'B' +_alnum['\U0001d436'] = 'C' +_alnum['\U0001d437'] = 'D' +_alnum['\U0001d438'] = 'E' +_alnum['\U0001d439'] = 'F' +_alnum['\U0001d43a'] = 'G' +_alnum['\U0001d43b'] = 'H' +_alnum['\U0001d43c'] = 'I' +_alnum['\U0001d43d'] = 'J' +_alnum['\U0001d43e'] = 'K' +_alnum['\U0001d43f'] = 'L' +_alnum['\U0001d440'] = 'M' +_alnum['\U0001d441'] = 'N' +_alnum['\U0001d442'] = 'O' +_alnum['\U0001d443'] = 'P' +_alnum['\U0001d444'] = 'Q' +_alnum['\U0001d445'] = 'R' +_alnum['\U0001d446'] = 'S' +_alnum['\U0001d447'] = 'T' +_alnum['\U0001d448'] = 'U' +_alnum['\U0001d449'] = 'V' +_alnum['\U0001d44a'] = 'W' +_alnum['\U0001d44b'] = 'X' +_alnum['\U0001d44c'] = 'Y' +_alnum['\U0001d44d'] = 'Z' +_alnum['\U0001d44e'] = 'a' +_alnum['\U0001d44f'] = 'b' +_alnum['\U0001d450'] = 'c' +_alnum['\U0001d451'] = 'd' +_alnum['\U0001d452'] = 'e' +_alnum['\U0001d453'] = 'f' +_alnum['\U0001d454'] = 'g' +_alnum['\U0001d456'] = 'i' +_alnum['\U0001d457'] = 'j' +_alnum['\U0001d458'] = 'k' +_alnum['\U0001d459'] = 'l' +_alnum['\U0001d45a'] = 'm' +_alnum['\U0001d45b'] = 'n' +_alnum['\U0001d45c'] = 'o' +_alnum['\U0001d45d'] = 'p' +_alnum['\U0001d45e'] = 'q' +_alnum['\U0001d45f'] = 'r' +_alnum['\U0001d460'] = 's' +_alnum['\U0001d461'] = 't' +_alnum['\U0001d462'] = 'u' +_alnum['\U0001d463'] = 'v' +_alnum['\U0001d464'] = 'w' +_alnum['\U0001d465'] = 'x' +_alnum['\U0001d466'] = 'y' +_alnum['\U0001d467'] = 'z' +_alnum['\U0001d468'] = 'A' +_alnum['\U0001d469'] = 'B' +_alnum['\U0001d46a'] = 'C' +_alnum['\U0001d46b'] = 'D' +_alnum['\U0001d46c'] = 'E' +_alnum['\U0001d46d'] = 'F' +_alnum['\U0001d46e'] = 'G' +_alnum['\U0001d46f'] = 'H' +_alnum['\U0001d470'] = 'I' +_alnum['\U0001d471'] = 'J' +_alnum['\U0001d472'] = 'K' +_alnum['\U0001d473'] = 'L' +_alnum['\U0001d474'] = 'M' +_alnum['\U0001d475'] = 'N' +_alnum['\U0001d476'] = 'O' +_alnum['\U0001d477'] = 'P' +_alnum['\U0001d478'] = 'Q' +_alnum['\U0001d479'] = 'R' +_alnum['\U0001d47a'] = 'S' +_alnum['\U0001d47b'] = 'T' +_alnum['\U0001d47c'] = 'U' +_alnum['\U0001d47d'] = 'V' +_alnum['\U0001d47e'] = 'W' +_alnum['\U0001d47f'] = 'X' +_alnum['\U0001d480'] = 'Y' +_alnum['\U0001d481'] = 'Z' +_alnum['\U0001d482'] = 'a' +_alnum['\U0001d483'] = 'b' +_alnum['\U0001d484'] = 'c' +_alnum['\U0001d485'] = 'd' +_alnum['\U0001d486'] = 'e' +_alnum['\U0001d487'] = 'f' +_alnum['\U0001d488'] = 'g' +_alnum['\U0001d489'] = 'h' +_alnum['\U0001d48a'] = 'i' +_alnum['\U0001d48b'] = 'j' +_alnum['\U0001d48c'] = 'k' +_alnum['\U0001d48d'] = 'l' +_alnum['\U0001d48e'] = 'm' +_alnum['\U0001d48f'] = 'n' +_alnum['\U0001d490'] = 'o' +_alnum['\U0001d491'] = 'p' +_alnum['\U0001d492'] = 'q' +_alnum['\U0001d493'] = 'r' +_alnum['\U0001d494'] = 's' +_alnum['\U0001d495'] = 't' +_alnum['\U0001d496'] = 'u' +_alnum['\U0001d497'] = 'v' +_alnum['\U0001d498'] = 'w' +_alnum['\U0001d499'] = 'x' +_alnum['\U0001d49a'] = 'y' +_alnum['\U0001d49b'] = 'z' +_alnum['\U0001d49c'] = 'A' +_alnum['\U0001d49e'] = 'C' +_alnum['\U0001d49f'] = 'D' +_alnum['\U0001d4a2'] = 'G' +_alnum['\U0001d4a5'] = 'J' +_alnum['\U0001d4a6'] = 'K' +_alnum['\U0001d4a9'] = 'N' +_alnum['\U0001d4aa'] = 'O' +_alnum['\U0001d4ab'] = 'P' +_alnum['\U0001d4ac'] = 'Q' +_alnum['\U0001d4ae'] = 'S' +_alnum['\U0001d4af'] = 'T' +_alnum['\U0001d4b0'] = 'U' +_alnum['\U0001d4b1'] = 'V' +_alnum['\U0001d4b2'] = 'W' +_alnum['\U0001d4b3'] = 'X' +_alnum['\U0001d4b4'] = 'Y' +_alnum['\U0001d4b5'] = 'Z' +_alnum['\U0001d4b6'] = 'a' +_alnum['\U0001d4b7'] = 'b' +_alnum['\U0001d4b8'] = 'c' +_alnum['\U0001d4b9'] = 'd' +_alnum['\U0001d4bb'] = 'f' +_alnum['\U0001d4bd'] = 'h' +_alnum['\U0001d4be'] = 'i' +_alnum['\U0001d4bf'] = 'j' +_alnum['\U0001d4c0'] = 'k' +_alnum['\U0001d4c1'] = 'l' +_alnum['\U0001d4c2'] = 'm' +_alnum['\U0001d4c3'] = 'n' +_alnum['\U0001d4c5'] = 'p' +_alnum['\U0001d4c6'] = 'q' +_alnum['\U0001d4c7'] = 'r' +_alnum['\U0001d4c8'] = 's' +_alnum['\U0001d4c9'] = 't' +_alnum['\U0001d4ca'] = 'u' +_alnum['\U0001d4cb'] = 'v' +_alnum['\U0001d4cc'] = 'w' +_alnum['\U0001d4cd'] = 'x' +_alnum['\U0001d4ce'] = 'y' +_alnum['\U0001d4cf'] = 'z' +_alnum['\U0001d4d0'] = 'A' +_alnum['\U0001d4d1'] = 'B' +_alnum['\U0001d4d2'] = 'C' +_alnum['\U0001d4d3'] = 'D' +_alnum['\U0001d4d4'] = 'E' +_alnum['\U0001d4d5'] = 'F' +_alnum['\U0001d4d6'] = 'G' +_alnum['\U0001d4d7'] = 'H' +_alnum['\U0001d4d8'] = 'I' +_alnum['\U0001d4d9'] = 'J' +_alnum['\U0001d4da'] = 'K' +_alnum['\U0001d4db'] = 'L' +_alnum['\U0001d4dc'] = 'M' +_alnum['\U0001d4dd'] = 'N' +_alnum['\U0001d4de'] = 'O' +_alnum['\U0001d4df'] = 'P' +_alnum['\U0001d4e0'] = 'Q' +_alnum['\U0001d4e1'] = 'R' +_alnum['\U0001d4e2'] = 'S' +_alnum['\U0001d4e3'] = 'T' +_alnum['\U0001d4e4'] = 'U' +_alnum['\U0001d4e5'] = 'V' +_alnum['\U0001d4e6'] = 'W' +_alnum['\U0001d4e7'] = 'X' +_alnum['\U0001d4e8'] = 'Y' +_alnum['\U0001d4e9'] = 'Z' +_alnum['\U0001d4ea'] = 'a' +_alnum['\U0001d4eb'] = 'b' +_alnum['\U0001d4ec'] = 'c' +_alnum['\U0001d4ed'] = 'd' +_alnum['\U0001d4ee'] = 'e' +_alnum['\U0001d4ef'] = 'f' +_alnum['\U0001d4f0'] = 'g' +_alnum['\U0001d4f1'] = 'h' +_alnum['\U0001d4f2'] = 'i' +_alnum['\U0001d4f3'] = 'j' +_alnum['\U0001d4f4'] = 'k' +_alnum['\U0001d4f5'] = 'l' +_alnum['\U0001d4f6'] = 'm' +_alnum['\U0001d4f7'] = 'n' +_alnum['\U0001d4f8'] = 'o' +_alnum['\U0001d4f9'] = 'p' +_alnum['\U0001d4fa'] = 'q' +_alnum['\U0001d4fb'] = 'r' +_alnum['\U0001d4fc'] = 's' +_alnum['\U0001d4fd'] = 't' +_alnum['\U0001d4fe'] = 'u' +_alnum['\U0001d4ff'] = 'v' +_alnum['\U0001d500'] = 'w' +_alnum['\U0001d501'] = 'x' +_alnum['\U0001d502'] = 'y' +_alnum['\U0001d503'] = 'z' +_alnum['\U0001d504'] = 'A' +_alnum['\U0001d505'] = 'B' +_alnum['\U0001d507'] = 'D' +_alnum['\U0001d508'] = 'E' +_alnum['\U0001d509'] = 'F' +_alnum['\U0001d50a'] = 'G' +_alnum['\U0001d50d'] = 'J' +_alnum['\U0001d50e'] = 'K' +_alnum['\U0001d50f'] = 'L' +_alnum['\U0001d510'] = 'M' +_alnum['\U0001d511'] = 'N' +_alnum['\U0001d512'] = 'O' +_alnum['\U0001d513'] = 'P' +_alnum['\U0001d514'] = 'Q' +_alnum['\U0001d516'] = 'S' +_alnum['\U0001d517'] = 'T' +_alnum['\U0001d518'] = 'U' +_alnum['\U0001d519'] = 'V' +_alnum['\U0001d51a'] = 'W' +_alnum['\U0001d51b'] = 'X' +_alnum['\U0001d51c'] = 'Y' +_alnum['\U0001d51e'] = 'a' +_alnum['\U0001d51f'] = 'b' +_alnum['\U0001d520'] = 'c' +_alnum['\U0001d521'] = 'd' +_alnum['\U0001d522'] = 'e' +_alnum['\U0001d523'] = 'f' +_alnum['\U0001d524'] = 'g' +_alnum['\U0001d525'] = 'h' +_alnum['\U0001d526'] = 'i' +_alnum['\U0001d527'] = 'j' +_alnum['\U0001d528'] = 'k' +_alnum['\U0001d529'] = 'l' +_alnum['\U0001d52a'] = 'm' +_alnum['\U0001d52b'] = 'n' +_alnum['\U0001d52c'] = 'o' +_alnum['\U0001d52d'] = 'p' +_alnum['\U0001d52e'] = 'q' +_alnum['\U0001d52f'] = 'r' +_alnum['\U0001d530'] = 's' +_alnum['\U0001d531'] = 't' +_alnum['\U0001d532'] = 'u' +_alnum['\U0001d533'] = 'v' +_alnum['\U0001d534'] = 'w' +_alnum['\U0001d535'] = 'x' +_alnum['\U0001d536'] = 'y' +_alnum['\U0001d537'] = 'z' +_alnum['\U0001d538'] = 'A' +_alnum['\U0001d539'] = 'B' +_alnum['\U0001d53b'] = 'D' +_alnum['\U0001d53c'] = 'E' +_alnum['\U0001d53d'] = 'F' +_alnum['\U0001d53e'] = 'G' +_alnum['\U0001d540'] = 'I' +_alnum['\U0001d541'] = 'J' +_alnum['\U0001d542'] = 'K' +_alnum['\U0001d543'] = 'L' +_alnum['\U0001d544'] = 'M' +_alnum['\U0001d546'] = 'O' +_alnum['\U0001d54a'] = 'S' +_alnum['\U0001d54b'] = 'T' +_alnum['\U0001d54c'] = 'U' +_alnum['\U0001d54d'] = 'V' +_alnum['\U0001d54e'] = 'W' +_alnum['\U0001d54f'] = 'X' +_alnum['\U0001d550'] = 'Y' +_alnum['\U0001d552'] = 'a' +_alnum['\U0001d553'] = 'b' +_alnum['\U0001d554'] = 'c' +_alnum['\U0001d555'] = 'd' +_alnum['\U0001d556'] = 'e' +_alnum['\U0001d557'] = 'f' +_alnum['\U0001d558'] = 'g' +_alnum['\U0001d559'] = 'h' +_alnum['\U0001d55a'] = 'i' +_alnum['\U0001d55b'] = 'j' +_alnum['\U0001d55c'] = 'k' +_alnum['\U0001d55d'] = 'l' +_alnum['\U0001d55e'] = 'm' +_alnum['\U0001d55f'] = 'n' +_alnum['\U0001d560'] = 'o' +_alnum['\U0001d561'] = 'p' +_alnum['\U0001d562'] = 'q' +_alnum['\U0001d563'] = 'r' +_alnum['\U0001d564'] = 's' +_alnum['\U0001d565'] = 't' +_alnum['\U0001d566'] = 'u' +_alnum['\U0001d567'] = 'v' +_alnum['\U0001d568'] = 'w' +_alnum['\U0001d569'] = 'x' +_alnum['\U0001d56a'] = 'y' +_alnum['\U0001d56b'] = 'z' +_alnum['\U0001d56c'] = 'A' +_alnum['\U0001d56d'] = 'B' +_alnum['\U0001d56e'] = 'C' +_alnum['\U0001d56f'] = 'D' +_alnum['\U0001d570'] = 'E' +_alnum['\U0001d571'] = 'F' +_alnum['\U0001d572'] = 'G' +_alnum['\U0001d573'] = 'H' +_alnum['\U0001d574'] = 'I' +_alnum['\U0001d575'] = 'J' +_alnum['\U0001d576'] = 'K' +_alnum['\U0001d577'] = 'L' +_alnum['\U0001d578'] = 'M' +_alnum['\U0001d579'] = 'N' +_alnum['\U0001d57a'] = 'O' +_alnum['\U0001d57b'] = 'P' +_alnum['\U0001d57c'] = 'Q' +_alnum['\U0001d57d'] = 'R' +_alnum['\U0001d57e'] = 'S' +_alnum['\U0001d57f'] = 'T' +_alnum['\U0001d580'] = 'U' +_alnum['\U0001d581'] = 'V' +_alnum['\U0001d582'] = 'W' +_alnum['\U0001d583'] = 'X' +_alnum['\U0001d584'] = 'Y' +_alnum['\U0001d585'] = 'Z' +_alnum['\U0001d586'] = 'a' +_alnum['\U0001d587'] = 'b' +_alnum['\U0001d588'] = 'c' +_alnum['\U0001d589'] = 'd' +_alnum['\U0001d58a'] = 'e' +_alnum['\U0001d58b'] = 'f' +_alnum['\U0001d58c'] = 'g' +_alnum['\U0001d58d'] = 'h' +_alnum['\U0001d58e'] = 'i' +_alnum['\U0001d58f'] = 'j' +_alnum['\U0001d590'] = 'k' +_alnum['\U0001d591'] = 'l' +_alnum['\U0001d592'] = 'm' +_alnum['\U0001d593'] = 'n' +_alnum['\U0001d594'] = 'o' +_alnum['\U0001d595'] = 'p' +_alnum['\U0001d596'] = 'q' +_alnum['\U0001d597'] = 'r' +_alnum['\U0001d598'] = 's' +_alnum['\U0001d599'] = 't' +_alnum['\U0001d59a'] = 'u' +_alnum['\U0001d59b'] = 'v' +_alnum['\U0001d59c'] = 'w' +_alnum['\U0001d59d'] = 'x' +_alnum['\U0001d59e'] = 'y' +_alnum['\U0001d59f'] = 'z' +_alnum['\U0001d5a0'] = 'A' +_alnum['\U0001d5a1'] = 'B' +_alnum['\U0001d5a2'] = 'C' +_alnum['\U0001d5a3'] = 'D' +_alnum['\U0001d5a4'] = 'E' +_alnum['\U0001d5a5'] = 'F' +_alnum['\U0001d5a6'] = 'G' +_alnum['\U0001d5a7'] = 'H' +_alnum['\U0001d5a8'] = 'I' +_alnum['\U0001d5a9'] = 'J' +_alnum['\U0001d5aa'] = 'K' +_alnum['\U0001d5ab'] = 'L' +_alnum['\U0001d5ac'] = 'M' +_alnum['\U0001d5ad'] = 'N' +_alnum['\U0001d5ae'] = 'O' +_alnum['\U0001d5af'] = 'P' +_alnum['\U0001d5b0'] = 'Q' +_alnum['\U0001d5b1'] = 'R' +_alnum['\U0001d5b2'] = 'S' +_alnum['\U0001d5b3'] = 'T' +_alnum['\U0001d5b4'] = 'U' +_alnum['\U0001d5b5'] = 'V' +_alnum['\U0001d5b6'] = 'W' +_alnum['\U0001d5b7'] = 'X' +_alnum['\U0001d5b8'] = 'Y' +_alnum['\U0001d5b9'] = 'Z' +_alnum['\U0001d5ba'] = 'a' +_alnum['\U0001d5bb'] = 'b' +_alnum['\U0001d5bc'] = 'c' +_alnum['\U0001d5bd'] = 'd' +_alnum['\U0001d5be'] = 'e' +_alnum['\U0001d5bf'] = 'f' +_alnum['\U0001d5c0'] = 'g' +_alnum['\U0001d5c1'] = 'h' +_alnum['\U0001d5c2'] = 'i' +_alnum['\U0001d5c3'] = 'j' +_alnum['\U0001d5c4'] = 'k' +_alnum['\U0001d5c5'] = 'l' +_alnum['\U0001d5c6'] = 'm' +_alnum['\U0001d5c7'] = 'n' +_alnum['\U0001d5c8'] = 'o' +_alnum['\U0001d5c9'] = 'p' +_alnum['\U0001d5ca'] = 'q' +_alnum['\U0001d5cb'] = 'r' +_alnum['\U0001d5cc'] = 's' +_alnum['\U0001d5cd'] = 't' +_alnum['\U0001d5ce'] = 'u' +_alnum['\U0001d5cf'] = 'v' +_alnum['\U0001d5d0'] = 'w' +_alnum['\U0001d5d1'] = 'x' +_alnum['\U0001d5d2'] = 'y' +_alnum['\U0001d5d3'] = 'z' +_alnum['\U0001d5d4'] = 'A' +_alnum['\U0001d5d5'] = 'B' +_alnum['\U0001d5d6'] = 'C' +_alnum['\U0001d5d7'] = 'D' +_alnum['\U0001d5d8'] = 'E' +_alnum['\U0001d5d9'] = 'F' +_alnum['\U0001d5da'] = 'G' +_alnum['\U0001d5db'] = 'H' +_alnum['\U0001d5dc'] = 'I' +_alnum['\U0001d5dd'] = 'J' +_alnum['\U0001d5de'] = 'K' +_alnum['\U0001d5df'] = 'L' +_alnum['\U0001d5e0'] = 'M' +_alnum['\U0001d5e1'] = 'N' +_alnum['\U0001d5e2'] = 'O' +_alnum['\U0001d5e3'] = 'P' +_alnum['\U0001d5e4'] = 'Q' +_alnum['\U0001d5e5'] = 'R' +_alnum['\U0001d5e6'] = 'S' +_alnum['\U0001d5e7'] = 'T' +_alnum['\U0001d5e8'] = 'U' +_alnum['\U0001d5e9'] = 'V' +_alnum['\U0001d5ea'] = 'W' +_alnum['\U0001d5eb'] = 'X' +_alnum['\U0001d5ec'] = 'Y' +_alnum['\U0001d5ed'] = 'Z' +_alnum['\U0001d5ee'] = 'a' +_alnum['\U0001d5ef'] = 'b' +_alnum['\U0001d5f0'] = 'c' +_alnum['\U0001d5f1'] = 'd' +_alnum['\U0001d5f2'] = 'e' +_alnum['\U0001d5f3'] = 'f' +_alnum['\U0001d5f4'] = 'g' +_alnum['\U0001d5f5'] = 'h' +_alnum['\U0001d5f6'] = 'i' +_alnum['\U0001d5f7'] = 'j' +_alnum['\U0001d5f8'] = 'k' +_alnum['\U0001d5f9'] = 'l' +_alnum['\U0001d5fa'] = 'm' +_alnum['\U0001d5fb'] = 'n' +_alnum['\U0001d5fc'] = 'o' +_alnum['\U0001d5fd'] = 'p' +_alnum['\U0001d5fe'] = 'q' +_alnum['\U0001d5ff'] = 'r' +_alnum['\U0001d600'] = 's' +_alnum['\U0001d601'] = 't' +_alnum['\U0001d602'] = 'u' +_alnum['\U0001d603'] = 'v' +_alnum['\U0001d604'] = 'w' +_alnum['\U0001d605'] = 'x' +_alnum['\U0001d606'] = 'y' +_alnum['\U0001d607'] = 'z' +_alnum['\U0001d608'] = 'A' +_alnum['\U0001d609'] = 'B' +_alnum['\U0001d60a'] = 'C' +_alnum['\U0001d60b'] = 'D' +_alnum['\U0001d60c'] = 'E' +_alnum['\U0001d60d'] = 'F' +_alnum['\U0001d60e'] = 'G' +_alnum['\U0001d60f'] = 'H' +_alnum['\U0001d610'] = 'I' +_alnum['\U0001d611'] = 'J' +_alnum['\U0001d612'] = 'K' +_alnum['\U0001d613'] = 'L' +_alnum['\U0001d614'] = 'M' +_alnum['\U0001d615'] = 'N' +_alnum['\U0001d616'] = 'O' +_alnum['\U0001d617'] = 'P' +_alnum['\U0001d618'] = 'Q' +_alnum['\U0001d619'] = 'R' +_alnum['\U0001d61a'] = 'S' +_alnum['\U0001d61b'] = 'T' +_alnum['\U0001d61c'] = 'U' +_alnum['\U0001d61d'] = 'V' +_alnum['\U0001d61e'] = 'W' +_alnum['\U0001d61f'] = 'X' +_alnum['\U0001d620'] = 'Y' +_alnum['\U0001d621'] = 'Z' +_alnum['\U0001d622'] = 'a' +_alnum['\U0001d623'] = 'b' +_alnum['\U0001d624'] = 'c' +_alnum['\U0001d625'] = 'd' +_alnum['\U0001d626'] = 'e' +_alnum['\U0001d627'] = 'f' +_alnum['\U0001d628'] = 'g' +_alnum['\U0001d629'] = 'h' +_alnum['\U0001d62a'] = 'i' +_alnum['\U0001d62b'] = 'j' +_alnum['\U0001d62c'] = 'k' +_alnum['\U0001d62d'] = 'l' +_alnum['\U0001d62e'] = 'm' +_alnum['\U0001d62f'] = 'n' +_alnum['\U0001d630'] = 'o' +_alnum['\U0001d631'] = 'p' +_alnum['\U0001d632'] = 'q' +_alnum['\U0001d633'] = 'r' +_alnum['\U0001d634'] = 's' +_alnum['\U0001d635'] = 't' +_alnum['\U0001d636'] = 'u' +_alnum['\U0001d637'] = 'v' +_alnum['\U0001d638'] = 'w' +_alnum['\U0001d639'] = 'x' +_alnum['\U0001d63a'] = 'y' +_alnum['\U0001d63b'] = 'z' +_alnum['\U0001d63c'] = 'A' +_alnum['\U0001d63d'] = 'B' +_alnum['\U0001d63e'] = 'C' +_alnum['\U0001d63f'] = 'D' +_alnum['\U0001d640'] = 'E' +_alnum['\U0001d641'] = 'F' +_alnum['\U0001d642'] = 'G' +_alnum['\U0001d643'] = 'H' +_alnum['\U0001d644'] = 'I' +_alnum['\U0001d645'] = 'J' +_alnum['\U0001d646'] = 'K' +_alnum['\U0001d647'] = 'L' +_alnum['\U0001d648'] = 'M' +_alnum['\U0001d649'] = 'N' +_alnum['\U0001d64a'] = 'O' +_alnum['\U0001d64b'] = 'P' +_alnum['\U0001d64c'] = 'Q' +_alnum['\U0001d64d'] = 'R' +_alnum['\U0001d64e'] = 'S' +_alnum['\U0001d64f'] = 'T' +_alnum['\U0001d650'] = 'U' +_alnum['\U0001d651'] = 'V' +_alnum['\U0001d652'] = 'W' +_alnum['\U0001d653'] = 'X' +_alnum['\U0001d654'] = 'Y' +_alnum['\U0001d655'] = 'Z' +_alnum['\U0001d656'] = 'a' +_alnum['\U0001d657'] = 'b' +_alnum['\U0001d658'] = 'c' +_alnum['\U0001d659'] = 'd' +_alnum['\U0001d65a'] = 'e' +_alnum['\U0001d65b'] = 'f' +_alnum['\U0001d65c'] = 'g' +_alnum['\U0001d65d'] = 'h' +_alnum['\U0001d65e'] = 'i' +_alnum['\U0001d65f'] = 'j' +_alnum['\U0001d660'] = 'k' +_alnum['\U0001d661'] = 'l' +_alnum['\U0001d662'] = 'm' +_alnum['\U0001d663'] = 'n' +_alnum['\U0001d664'] = 'o' +_alnum['\U0001d665'] = 'p' +_alnum['\U0001d666'] = 'q' +_alnum['\U0001d667'] = 'r' +_alnum['\U0001d668'] = 's' +_alnum['\U0001d669'] = 't' +_alnum['\U0001d66a'] = 'u' +_alnum['\U0001d66b'] = 'v' +_alnum['\U0001d66c'] = 'w' +_alnum['\U0001d66d'] = 'x' +_alnum['\U0001d66e'] = 'y' +_alnum['\U0001d66f'] = 'z' +_alnum['\U0001d670'] = 'A' +_alnum['\U0001d671'] = 'B' +_alnum['\U0001d672'] = 'C' +_alnum['\U0001d673'] = 'D' +_alnum['\U0001d674'] = 'E' +_alnum['\U0001d675'] = 'F' +_alnum['\U0001d676'] = 'G' +_alnum['\U0001d677'] = 'H' +_alnum['\U0001d678'] = 'I' +_alnum['\U0001d679'] = 'J' +_alnum['\U0001d67a'] = 'K' +_alnum['\U0001d67b'] = 'L' +_alnum['\U0001d67c'] = 'M' +_alnum['\U0001d67d'] = 'N' +_alnum['\U0001d67e'] = 'O' +_alnum['\U0001d67f'] = 'P' +_alnum['\U0001d680'] = 'Q' +_alnum['\U0001d681'] = 'R' +_alnum['\U0001d682'] = 'S' +_alnum['\U0001d683'] = 'T' +_alnum['\U0001d684'] = 'U' +_alnum['\U0001d685'] = 'V' +_alnum['\U0001d686'] = 'W' +_alnum['\U0001d687'] = 'X' +_alnum['\U0001d688'] = 'Y' +_alnum['\U0001d689'] = 'Z' +_alnum['\U0001d68a'] = 'a' +_alnum['\U0001d68b'] = 'b' +_alnum['\U0001d68c'] = 'c' +_alnum['\U0001d68d'] = 'd' +_alnum['\U0001d68e'] = 'e' +_alnum['\U0001d68f'] = 'f' +_alnum['\U0001d690'] = 'g' +_alnum['\U0001d691'] = 'h' +_alnum['\U0001d692'] = 'i' +_alnum['\U0001d693'] = 'j' +_alnum['\U0001d694'] = 'k' +_alnum['\U0001d695'] = 'l' +_alnum['\U0001d696'] = 'm' +_alnum['\U0001d697'] = 'n' +_alnum['\U0001d698'] = 'o' +_alnum['\U0001d699'] = 'p' +_alnum['\U0001d69a'] = 'q' +_alnum['\U0001d69b'] = 'r' +_alnum['\U0001d69c'] = 's' +_alnum['\U0001d69d'] = 't' +_alnum['\U0001d69e'] = 'u' +_alnum['\U0001d69f'] = 'v' +_alnum['\U0001d6a0'] = 'w' +_alnum['\U0001d6a1'] = 'x' +_alnum['\U0001d6a2'] = 'y' +_alnum['\U0001d6a3'] = 'z' +_alnum['\U0001d6a4'] = 'i' +_alnum['\U0001d6a5'] = 'j' +_alnum['\U0001d6a8'] = 'Α' +_alnum['\U0001d6a9'] = 'Β' +_alnum['\U0001d6aa'] = 'Γ' +_alnum['\U0001d6ab'] = 'Δ' +_alnum['\U0001d6ac'] = 'Ε' +_alnum['\U0001d6ad'] = 'Ζ' +_alnum['\U0001d6ae'] = 'Η' +_alnum['\U0001d6af'] = 'ϴ' +_alnum['\U0001d6b0'] = 'Ι' +_alnum['\U0001d6b1'] = 'Κ' +_alnum['\U0001d6b2'] = 'Λ' +_alnum['\U0001d6b3'] = 'Μ' +_alnum['\U0001d6b4'] = 'Ν' +_alnum['\U0001d6b5'] = 'Ξ' +_alnum['\U0001d6b6'] = 'Ο' +_alnum['\U0001d6b7'] = 'Π' +_alnum['\U0001d6b8'] = 'Ρ' +_alnum['\U0001d6b9'] = 'ϴ' +_alnum['\U0001d6ba'] = 'Σ' +_alnum['\U0001d6bb'] = 'Τ' +_alnum['\U0001d6bc'] = 'Υ' +_alnum['\U0001d6bd'] = 'Φ' +_alnum['\U0001d6be'] = 'Χ' +_alnum['\U0001d6bf'] = 'Ψ' +_alnum['\U0001d6c0'] = 'Ω' +_alnum['\U0001d6c1'] = '∇' +_alnum['\U0001d6c2'] = 'α' +_alnum['\U0001d6c3'] = 'β' +_alnum['\U0001d6c4'] = 'γ' +_alnum['\U0001d6c5'] = 'δ' +_alnum['\U0001d6c6'] = 'ε' +_alnum['\U0001d6c7'] = 'ζ' +_alnum['\U0001d6c8'] = 'η' +_alnum['\U0001d6c9'] = 'θ' +_alnum['\U0001d6ca'] = 'ι' +_alnum['\U0001d6cb'] = 'κ' +_alnum['\U0001d6cc'] = 'λ' +_alnum['\U0001d6cd'] = 'μ' +_alnum['\U0001d6ce'] = 'ν' +_alnum['\U0001d6cf'] = 'ξ' +_alnum['\U0001d6d0'] = 'ο' +_alnum['\U0001d6d1'] = 'π' +_alnum['\U0001d6d2'] = 'ρ' +_alnum['\U0001d6d3'] = 'ς' +_alnum['\U0001d6d4'] = 'σ' +_alnum['\U0001d6d5'] = 'τ' +_alnum['\U0001d6d6'] = 'υ' +_alnum['\U0001d6d7'] = 'φ' +_alnum['\U0001d6d8'] = 'χ' +_alnum['\U0001d6d9'] = 'ψ' +_alnum['\U0001d6da'] = 'ω' +_alnum['\U0001d6db'] = '∂' +_alnum['\U0001d6dc'] = 'ϵ' +_alnum['\U0001d6dd'] = 'ϑ' +_alnum['\U0001d6de'] = 'ϰ' +_alnum['\U0001d6df'] = 'ϕ' +_alnum['\U0001d6e0'] = 'ϱ' +_alnum['\U0001d6e1'] = 'ϖ' +_alnum['\U0001d6e2'] = 'Α' +_alnum['\U0001d6e3'] = 'Β' +_alnum['\U0001d6e4'] = 'Γ' +_alnum['\U0001d6e5'] = 'Δ' +_alnum['\U0001d6e6'] = 'Ε' +_alnum['\U0001d6e7'] = 'Ζ' +_alnum['\U0001d6e8'] = 'Η' +_alnum['\U0001d6e9'] = 'ϴ' +_alnum['\U0001d6ea'] = 'Ι' +_alnum['\U0001d6eb'] = 'Κ' +_alnum['\U0001d6ec'] = 'Λ' +_alnum['\U0001d6ed'] = 'Μ' +_alnum['\U0001d6ee'] = 'Ν' +_alnum['\U0001d6ef'] = 'Ξ' +_alnum['\U0001d6f0'] = 'Ο' +_alnum['\U0001d6f1'] = 'Π' +_alnum['\U0001d6f2'] = 'Ρ' +_alnum['\U0001d6f3'] = 'ϴ' +_alnum['\U0001d6f4'] = 'Σ' +_alnum['\U0001d6f5'] = 'Τ' +_alnum['\U0001d6f6'] = 'Υ' +_alnum['\U0001d6f7'] = 'Φ' +_alnum['\U0001d6f8'] = 'Χ' +_alnum['\U0001d6f9'] = 'Ψ' +_alnum['\U0001d6fa'] = 'Ω' +_alnum['\U0001d6fb'] = '∇' +_alnum['\U0001d6fc'] = 'α' +_alnum['\U0001d6fd'] = 'β' +_alnum['\U0001d6fe'] = 'γ' +_alnum['\U0001d6ff'] = 'δ' +_alnum['\U0001d700'] = 'ε' +_alnum['\U0001d701'] = 'ζ' +_alnum['\U0001d702'] = 'η' +_alnum['\U0001d703'] = 'θ' +_alnum['\U0001d704'] = 'ι' +_alnum['\U0001d705'] = 'κ' +_alnum['\U0001d706'] = 'λ' +_alnum['\U0001d707'] = 'μ' +_alnum['\U0001d708'] = 'ν' +_alnum['\U0001d709'] = 'ξ' +_alnum['\U0001d70a'] = 'ο' +_alnum['\U0001d70b'] = 'π' +_alnum['\U0001d70c'] = 'ρ' +_alnum['\U0001d70d'] = 'ς' +_alnum['\U0001d70e'] = 'σ' +_alnum['\U0001d70f'] = 'τ' +_alnum['\U0001d710'] = 'υ' +_alnum['\U0001d711'] = 'φ' +_alnum['\U0001d712'] = 'χ' +_alnum['\U0001d713'] = 'ψ' +_alnum['\U0001d714'] = 'ω' +_alnum['\U0001d715'] = '∂' +_alnum['\U0001d716'] = 'ϵ' +_alnum['\U0001d717'] = 'ϑ' +_alnum['\U0001d718'] = 'ϰ' +_alnum['\U0001d719'] = 'ϕ' +_alnum['\U0001d71a'] = 'ϱ' +_alnum['\U0001d71b'] = 'ϖ' +_alnum['\U0001d71c'] = 'Α' +_alnum['\U0001d71d'] = 'Β' +_alnum['\U0001d71e'] = 'Γ' +_alnum['\U0001d71f'] = 'Δ' +_alnum['\U0001d720'] = 'Ε' +_alnum['\U0001d721'] = 'Ζ' +_alnum['\U0001d722'] = 'Η' +_alnum['\U0001d723'] = 'ϴ' +_alnum['\U0001d724'] = 'Ι' +_alnum['\U0001d725'] = 'Κ' +_alnum['\U0001d726'] = 'Λ' +_alnum['\U0001d727'] = 'Μ' +_alnum['\U0001d728'] = 'Ν' +_alnum['\U0001d729'] = 'Ξ' +_alnum['\U0001d72a'] = 'Ο' +_alnum['\U0001d72b'] = 'Π' +_alnum['\U0001d72c'] = 'Ρ' +_alnum['\U0001d72d'] = 'ϴ' +_alnum['\U0001d72e'] = 'Σ' +_alnum['\U0001d72f'] = 'Τ' +_alnum['\U0001d730'] = 'Υ' +_alnum['\U0001d731'] = 'Φ' +_alnum['\U0001d732'] = 'Χ' +_alnum['\U0001d733'] = 'Ψ' +_alnum['\U0001d734'] = 'Ω' +_alnum['\U0001d735'] = '∇' +_alnum['\U0001d736'] = 'α' +_alnum['\U0001d737'] = 'β' +_alnum['\U0001d738'] = 'γ' +_alnum['\U0001d739'] = 'δ' +_alnum['\U0001d73a'] = 'ε' +_alnum['\U0001d73b'] = 'ζ' +_alnum['\U0001d73c'] = 'η' +_alnum['\U0001d73d'] = 'θ' +_alnum['\U0001d73e'] = 'ι' +_alnum['\U0001d73f'] = 'κ' +_alnum['\U0001d740'] = 'λ' +_alnum['\U0001d741'] = 'μ' +_alnum['\U0001d742'] = 'ν' +_alnum['\U0001d743'] = 'ξ' +_alnum['\U0001d744'] = 'ο' +_alnum['\U0001d745'] = 'π' +_alnum['\U0001d746'] = 'ρ' +_alnum['\U0001d747'] = 'ς' +_alnum['\U0001d748'] = 'σ' +_alnum['\U0001d749'] = 'τ' +_alnum['\U0001d74a'] = 'υ' +_alnum['\U0001d74b'] = 'φ' +_alnum['\U0001d74c'] = 'χ' +_alnum['\U0001d74d'] = 'ψ' +_alnum['\U0001d74e'] = 'ω' +_alnum['\U0001d74f'] = '∂' +_alnum['\U0001d750'] = 'ϵ' +_alnum['\U0001d751'] = 'ϑ' +_alnum['\U0001d752'] = 'ϰ' +_alnum['\U0001d753'] = 'ϕ' +_alnum['\U0001d754'] = 'ϱ' +_alnum['\U0001d755'] = 'ϖ' +_alnum['\U0001d756'] = 'Α' +_alnum['\U0001d757'] = 'Β' +_alnum['\U0001d758'] = 'Γ' +_alnum['\U0001d759'] = 'Δ' +_alnum['\U0001d75a'] = 'Ε' +_alnum['\U0001d75b'] = 'Ζ' +_alnum['\U0001d75c'] = 'Η' +_alnum['\U0001d75d'] = 'ϴ' +_alnum['\U0001d75e'] = 'Ι' +_alnum['\U0001d75f'] = 'Κ' +_alnum['\U0001d760'] = 'Λ' +_alnum['\U0001d761'] = 'Μ' +_alnum['\U0001d762'] = 'Ν' +_alnum['\U0001d763'] = 'Ξ' +_alnum['\U0001d764'] = 'Ο' +_alnum['\U0001d765'] = 'Π' +_alnum['\U0001d766'] = 'Ρ' +_alnum['\U0001d767'] = 'ϴ' +_alnum['\U0001d768'] = 'Σ' +_alnum['\U0001d769'] = 'Τ' +_alnum['\U0001d76a'] = 'Υ' +_alnum['\U0001d76b'] = 'Φ' +_alnum['\U0001d76c'] = 'Χ' +_alnum['\U0001d76d'] = 'Ψ' +_alnum['\U0001d76e'] = 'Ω' +_alnum['\U0001d76f'] = '∇' +_alnum['\U0001d770'] = 'α' +_alnum['\U0001d771'] = 'β' +_alnum['\U0001d772'] = 'γ' +_alnum['\U0001d773'] = 'δ' +_alnum['\U0001d774'] = 'ε' +_alnum['\U0001d775'] = 'ζ' +_alnum['\U0001d776'] = 'η' +_alnum['\U0001d777'] = 'θ' +_alnum['\U0001d778'] = 'ι' +_alnum['\U0001d779'] = 'κ' +_alnum['\U0001d77a'] = 'λ' +_alnum['\U0001d77b'] = 'μ' +_alnum['\U0001d77c'] = 'ν' +_alnum['\U0001d77d'] = 'ξ' +_alnum['\U0001d77e'] = 'ο' +_alnum['\U0001d77f'] = 'π' +_alnum['\U0001d780'] = 'ρ' +_alnum['\U0001d781'] = 'ς' +_alnum['\U0001d782'] = 'σ' +_alnum['\U0001d783'] = 'τ' +_alnum['\U0001d784'] = 'υ' +_alnum['\U0001d785'] = 'φ' +_alnum['\U0001d786'] = 'χ' +_alnum['\U0001d787'] = 'ψ' +_alnum['\U0001d788'] = 'ω' +_alnum['\U0001d789'] = '∂' +_alnum['\U0001d78a'] = 'ϵ' +_alnum['\U0001d78b'] = 'ϑ' +_alnum['\U0001d78c'] = 'ϰ' +_alnum['\U0001d78d'] = 'ϕ' +_alnum['\U0001d78e'] = 'ϱ' +_alnum['\U0001d78f'] = 'ϖ' +_alnum['\U0001d790'] = 'Α' +_alnum['\U0001d791'] = 'Β' +_alnum['\U0001d792'] = 'Γ' +_alnum['\U0001d793'] = 'Δ' +_alnum['\U0001d794'] = 'Ε' +_alnum['\U0001d795'] = 'Ζ' +_alnum['\U0001d796'] = 'Η' +_alnum['\U0001d797'] = 'ϴ' +_alnum['\U0001d798'] = 'Ι' +_alnum['\U0001d799'] = 'Κ' +_alnum['\U0001d79a'] = 'Λ' +_alnum['\U0001d79b'] = 'Μ' +_alnum['\U0001d79c'] = 'Ν' +_alnum['\U0001d79d'] = 'Ξ' +_alnum['\U0001d79e'] = 'Ο' +_alnum['\U0001d79f'] = 'Π' +_alnum['\U0001d7a0'] = 'Ρ' +_alnum['\U0001d7a1'] = 'ϴ' +_alnum['\U0001d7a2'] = 'Σ' +_alnum['\U0001d7a3'] = 'Τ' +_alnum['\U0001d7a4'] = 'Υ' +_alnum['\U0001d7a5'] = 'Φ' +_alnum['\U0001d7a6'] = 'Χ' +_alnum['\U0001d7a7'] = 'Ψ' +_alnum['\U0001d7a8'] = 'Ω' +_alnum['\U0001d7a9'] = '∇' +_alnum['\U0001d7aa'] = 'α' +_alnum['\U0001d7ab'] = 'β' +_alnum['\U0001d7ac'] = 'γ' +_alnum['\U0001d7ad'] = 'δ' +_alnum['\U0001d7ae'] = 'ε' +_alnum['\U0001d7af'] = 'ζ' +_alnum['\U0001d7b0'] = 'η' +_alnum['\U0001d7b1'] = 'θ' +_alnum['\U0001d7b2'] = 'ι' +_alnum['\U0001d7b3'] = 'κ' +_alnum['\U0001d7b4'] = 'λ' +_alnum['\U0001d7b5'] = 'μ' +_alnum['\U0001d7b6'] = 'ν' +_alnum['\U0001d7b7'] = 'ξ' +_alnum['\U0001d7b8'] = 'ο' +_alnum['\U0001d7b9'] = 'π' +_alnum['\U0001d7ba'] = 'ρ' +_alnum['\U0001d7bb'] = 'ς' +_alnum['\U0001d7bc'] = 'σ' +_alnum['\U0001d7bd'] = 'τ' +_alnum['\U0001d7be'] = 'υ' +_alnum['\U0001d7bf'] = 'φ' +_alnum['\U0001d7c0'] = 'χ' +_alnum['\U0001d7c1'] = 'ψ' +_alnum['\U0001d7c2'] = 'ω' +_alnum['\U0001d7c3'] = '∂' +_alnum['\U0001d7c4'] = 'ϵ' +_alnum['\U0001d7c5'] = 'ϑ' +_alnum['\U0001d7c6'] = 'ϰ' +_alnum['\U0001d7c7'] = 'ϕ' +_alnum['\U0001d7c8'] = 'ϱ' +_alnum['\U0001d7c9'] = 'ϖ' +_alnum['\U0001d7ca'] = 'Ϝ' +_alnum['\U0001d7cb'] = 'ϝ' +_alnum['\U0001d7ce'] = '0' +_alnum['\U0001d7cf'] = '1' +_alnum['\U0001d7d0'] = '2' +_alnum['\U0001d7d1'] = '3' +_alnum['\U0001d7d2'] = '4' +_alnum['\U0001d7d3'] = '5' +_alnum['\U0001d7d4'] = '6' +_alnum['\U0001d7d5'] = '7' +_alnum['\U0001d7d6'] = '8' +_alnum['\U0001d7d7'] = '9' +_alnum['\U0001d7d8'] = '0' +_alnum['\U0001d7d9'] = '1' +_alnum['\U0001d7da'] = '2' +_alnum['\U0001d7db'] = '3' +_alnum['\U0001d7dc'] = '4' +_alnum['\U0001d7dd'] = '5' +_alnum['\U0001d7de'] = '6' +_alnum['\U0001d7df'] = '7' +_alnum['\U0001d7e0'] = '8' +_alnum['\U0001d7e1'] = '9' +_alnum['\U0001d7e2'] = '0' +_alnum['\U0001d7e3'] = '1' +_alnum['\U0001d7e4'] = '2' +_alnum['\U0001d7e5'] = '3' +_alnum['\U0001d7e6'] = '4' +_alnum['\U0001d7e7'] = '5' +_alnum['\U0001d7e8'] = '6' +_alnum['\U0001d7e9'] = '7' +_alnum['\U0001d7ea'] = '8' +_alnum['\U0001d7eb'] = '9' +_alnum['\U0001d7ec'] = '0' +_alnum['\U0001d7ed'] = '1' +_alnum['\U0001d7ee'] = '2' +_alnum['\U0001d7ef'] = '3' +_alnum['\U0001d7f0'] = '4' +_alnum['\U0001d7f1'] = '5' +_alnum['\U0001d7f2'] = '6' +_alnum['\U0001d7f3'] = '7' +_alnum['\U0001d7f4'] = '8' +_alnum['\U0001d7f5'] = '9' +_alnum['\U0001d7f6'] = '0' +_alnum['\U0001d7f7'] = '1' +_alnum['\U0001d7f8'] = '2' +_alnum['\U0001d7f9'] = '3' +_alnum['\U0001d7fa'] = '4' +_alnum['\U0001d7fb'] = '5' +_alnum['\U0001d7fc'] = '6' +_alnum['\U0001d7fd'] = '7' +_alnum['\U0001d7fe'] = '8' +_alnum['\U0001d7ff'] = '9' + +_bold = range(0x1d400, 0x1d434) +_italic = range(0x1d434, 0x1d468) +_boldItalic = range(0x1d468, 0x1d49c) +_script = range(0x1d49c, 0x1d4d0) +_boldScript = range(0x1d4d0, 0x1d504) +_fraktur = range(0x1d504, 0x1d538) +_doubleStruck = range(0x1d538, 0x1d56c) +_boldFraktur = range(0x1d56c, 0x1d5a0) +_sansSerif = range(0x1d5a0, 0x1d5d4) +_sansSerifBold = range(0x1d5d4, 0x1d608) +_sansSerifItalic = range(0x1d608, 0x1d63c) +_sansSerifBoldItalic = range(0x1d63c, 0x1d670) +_monospace = range(0x1d670, 0x1d6a4) +_dotless = range(0x1d6a4, 0x1d6a8) +_boldGreek = range(0x1d6a8, 0x1d6e2) +_italicGreek = range(0x1d6e2, 0x1d71c) +_boldItalicGreek = range(0x1d71c, 0x1d756) +_sansSerifBoldGreek = range(0x1d756, 0x1d790) +_sansSerifBoldItalicGreek = range(0x1d790, 0x1d7ca) +_boldGreekDigamma = range(0x1d7ca, 0x1d7cc) +_boldDigits = range(0x1d7ce, 0x1d7d8) +_doubleStruckDigits = range(0x1d7d8, 0x1d7e2) +_sansSerifDigits = range(0x1d7e2, 0x1d7ec) +_sansSerifBoldDigits = range(0x1d7ec, 0x1d7f6) +_monospaceDigits = range(0x1d7f6, 0x1d800) +_otherDoubleStruck = [0x2102, 0x210d, 0x2115, 0x2119, 0x211a, 0x211d, 0x2124] +_otherFraktur = [0x212d, 0x210c, 0x2111, 0x211c, 0x2128] +_otherItalic = [0x210e] +_otherScript = [0x212c, + 0x2130, + 0x2131, + 0x210b, + 0x2110, + 0x2112, + 0x2133, + 0x211b, + 0x212f, + 0x210a, + 0x2134] + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +BOLD = C_('math symbol', 'bold %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +ITALIC = C_('math symbol', 'italic %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +BOLD_ITALIC = C_('math symbol', 'bold italic %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +SCRIPT = C_('math symbol', 'script %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +BOLD_SCRIPT = C_('math symbol', 'bold script %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +FRAKTUR = C_('math symbol', 'fraktur %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +DOUBLE_STRUCK = C_('math symbol', 'double-struck %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +BOLD_FRAKTUR = C_('math symbol', 'bold fraktur %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +SANS_SERIF = C_('math symbol', 'sans-serif %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +SANS_SERIF_BOLD = C_('math symbol', 'sans-serif bold %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +SANS_SERIF_ITALIC = C_('math symbol', 'sans-serif italic %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +SANS_SERIF_BOLD_ITALIC = C_('math symbol', 'sans-serif bold italic %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +MONOSPACE = C_('math symbol', 'monospace %s') + +# Translators: Unicode has a large set of characters consisting of a common +# alphanumeric symbol and a style. For instance, character 1D400 is a bold A, +# 1D468 is a bold italic A, 1D4D0 is a bold script A,, etc., etc. These styles +# can have specific meanings in mathematics and thus should be spoken along +# with the alphanumeric character. However, given the vast quantity of these +# characters, string substitution is being used with the substituted string +# being a single alphanumeric character. The full set of symbols can be found +# at http://www.unicode.org/charts/PDF/U1D400.pdf. +DOTLESS = C_('math symbol', 'dotless %s') + +# Translators: this is the spoken representation for the character '←' (U+2190) +_arrows['\u2190'] = C_('math symbol', 'left arrow') + +# Translators: this is the spoken representation for the character '↑' (U+2191) +_arrows['\u2191'] = C_('math symbol', 'up arrow') + +# Translators: this is the spoken representation for the character '→' (U+2192) +_arrows['\u2192'] = C_('math symbol', 'right arrow') + +# Translators: this is the spoken representation for the character '↓' (U+2193) +_arrows['\u2193'] = C_('math symbol', 'down arrow') + +# Translators: this is the spoken representation for the character '↔' (U+2194) +_arrows['\u2194'] = C_('math symbol', 'left right arrow') + +# Translators: this is the spoken representation for the character '↕' (U+2195) +_arrows['\u2195'] = C_('math symbol', 'up down arrow') + +# Translators: this is the spoken representation for the character '↖' (U+2196) +_arrows['\u2196'] = C_('math symbol', 'north west arrow') + +# Translators: this is the spoken representation for the character '↗' (U+2197) +_arrows['\u2197'] = C_('math symbol', 'north east arrow') + +# Translators: this is the spoken representation for the character '↘' (U+2198) +_arrows['\u2198'] = C_('math symbol', 'south east arrow') + +# Translators: this is the spoken representation for the character '↤' (U+21a4) +_arrows['\u21a4'] = C_('math symbol', 'left arrow from bar') + +# Translators: this is the spoken representation for the character '↥' (U+21a5) +_arrows['\u21a5'] = C_('math symbol', 'up arrow from bar') + +# Translators: this is the spoken representation for the character '↦' (U+21a6) +_arrows['\u21a6'] = C_('math symbol', 'right arrow from bar') + +# Translators: this is the spoken representation for the character '↧' (U+21a7) +_arrows['\u21a7'] = C_('math symbol', 'down arrow from bar') + +# Translators: this is the spoken representation for the character '⇐' (U+21d0) +_arrows['\u21d0'] = C_('math symbol', 'left double arrow') + +# Translators: this is the spoken representation for the character '⇑' (U+21d1) +_arrows['\u21d1'] = C_('math symbol', 'up double arrow') + +# Translators: this is the spoken representation for the character '⇒' (U+21d2) +_arrows['\u21d2'] = C_('math symbol', 'right double arrow') + +# Translators: this is the spoken representation for the character '⇓' (U+21d3) +_arrows['\u21d3'] = C_('math symbol', 'down double arrow') + +# Translators: this is the spoken representation for the character '⇔' (U+21d4) +_arrows['\u21d4'] = C_('math symbol', 'left right double arrow') + +# Translators: this is the spoken representation for the character '⇕' (U+21d5) +_arrows['\u21d5'] = C_('math symbol', 'up down double arrow') + +# Translators: this is the spoken representation for the character '⇖' (U+21d6) +_arrows['\u21d6'] = C_('math symbol', 'north west double arrow') + +# Translators: this is the spoken representation for the character '⇗' (U+21d7) +_arrows['\u21d7'] = C_('math symbol', 'north east double arrow') + +# Translators: this is the spoken representation for the character '⇘' (U+21d8) +_arrows['\u21d8'] = C_('math symbol', 'south east double arrow') + +# Translators: this is the spoken representation for the character '⇙' (U+21d9) +_arrows['\u21d9'] = C_('math symbol', 'south west double arrow') + +# Translators: this is the spoken representation for the character '➔' (U+2794) +_arrows['\u2794'] = C_('math symbol', 'right-pointing arrow') + +# Translators: this is the spoken representation for the character '➢' (U+27a2) +_arrows['\u27a2'] = C_('math symbol', 'right-pointing arrowhead') + +# Translators: this is the spoken word for the character '-' (U+002d) when used +# as a MathML operator. +_operators["\u002d"] = C_('math symbol', 'minus') + +# Translators: this is the spoken word for the character '<' (U+003c) when used +# as a MathML operator. +_operators["\u003c"] = C_('math symbol', 'less than') + +# Translators: this is the spoken word for the character '>' (U+003e) when used +# as a MathML operator. +_operators["\u003e"] = C_('math symbol', 'greater than') + +# Translators: this is the spoken word for the character '^' (U+005e) when used +# as a MathML operator. +_operators['\u005e'] = C_('math symbol', 'circumflex') + +# Translators: this is the spoken word for the character 'ˇ' (U+02c7) when used +# as a MathML operator. +_operators['\u02c7'] = C_('math symbol', 'háček') + +# Translators: this is the spoken word for the character '˘' (U+02d8) when used +# as a MathML operator. +_operators['\u02d8'] = C_('math symbol', 'breve') + +# Translators: this is the spoken word for the character '˙' (U+02d9) when used +# as a MathML operator. +_operators['\u02d9'] = C_('math symbol', 'dot') + +# Translators: this is the spoken word for the character '‖' (U+2016) when used +# as a MathML operator. +_operators['\u2016'] = C_('math symbol', 'double vertical line') + +# Translators: this is the spoken representation for the character '…' (U+2026) +_operators['\u2026'] = C_('math symbol', 'horizontal ellipsis') + +# Translators: this is the spoken representation for the character '∀' (U+2200) +_operators['\u2200'] = C_('math symbol', 'for all') + +# Translators: this is the spoken representation for the character '∁' (U+2201) +_operators['\u2201'] = C_('math symbol', 'complement') + +# Translators: this is the spoken representation for the character '∂' (U+2202) +_operators['\u2202'] = C_('math symbol', 'partial differential') + +# Translators: this is the spoken representation for the character '∃' (U+2203) +_operators['\u2203'] = C_('math symbol', 'there exists') + +# Translators: this is the spoken representation for the character '∄' (U+2204) +_operators['\u2204'] = C_('math symbol', 'there does not exist') + +# Translators: this is the spoken representation for the character '∅' (U+2205) +_operators['\u2205'] = C_('math symbol', 'empty set') + +# Translators: this is the spoken representation for the character '∆' (U+2206) +_operators['\u2206'] = C_('math symbol', 'increment') + +# Translators: this is the spoken representation for the character '∇' (U+2207) +_operators['\u2207'] = C_('math symbol', 'nabla') + +# Translators: this is the spoken representation for the character '∈' (U+2208) +_operators['\u2208'] = C_('math symbol', 'element of') + +# Translators: this is the spoken representation for the character '∉' (U+2209) +_operators['\u2209'] = C_('math symbol', 'not an element of') + +# Translators: this is the spoken representation for the character '∊' (U+220a) +_operators['\u220a'] = C_('math symbol', 'small element of') + +# Translators: this is the spoken representation for the character '∋' (U+220b) +_operators['\u220b'] = C_('math symbol', 'contains as a member') + +# Translators: this is the spoken representation for the character '∌' (U+220c) +_operators['\u220c'] = C_('math symbol', 'does not contain as a member') + +# Translators: this is the spoken representation for the character '∍' (U+220d) +_operators['\u220d'] = C_('math symbol', 'small contains as a member') + +# Translators: this is the spoken representation for the character '∎' (U+220e) +_operators['\u220e'] = C_('math symbol', 'end of proof') + +# Translators: this is the spoken representation for the character '∏' (U+220f) +_operators['\u220f'] = C_('math symbol', 'product') + +# Translators: this is the spoken representation for the character '∐' (U+2210) +_operators['\u2210'] = C_('math symbol', 'coproduct') + +# Translators: this is the spoken representation for the character '∑' (U+2211) +_operators['\u2211'] = C_('math symbol', 'sum') + +# Translators: this is the spoken representation for the character '−' (U+2212) +_operators['\u2212'] = C_('math symbol', 'minus') + +# Translators: this is the spoken representation for the character '∓' (U+2213) +_operators['\u2213'] = C_('math symbol', 'minus or plus') + +# Translators: this is the spoken representation for the character '∔' (U+2214) +_operators['\u2214'] = C_('math symbol', 'dot plus') + +# Translators: this is the spoken representation for the character '∕' (U+2215) +_operators['\u2215'] = C_('math symbol', 'division slash') + +# Translators: this is the spoken representation for the character '∖' (U+2216) +_operators['\u2216'] = C_('math symbol', 'set minus') + +# Translators: this is the spoken representation for the character '∗' (U+2217) +_operators['\u2217'] = C_('math symbol', 'asterisk operator') + +# Translators: this is the spoken representation for the character '∘' (U+2218) +_operators['\u2218'] = C_('math symbol', 'ring operator') + +# Translators: this is the spoken representation for the character '∙' (U+2219) +_operators['\u2219'] = C_('math symbol', 'bullet operator') + +# Translators: this is the spoken representation for the character '√' (U+221a) +_operators['\u221a'] = C_('math symbol', 'square root') + +# Translators: this is the spoken representation for the character '∛' (U+221b) +_operators['\u221b'] = C_('math symbol', 'cube root') + +# Translators: this is the spoken representation for the character '∜' (U+221c) +_operators['\u221c'] = C_('math symbol', 'fourth root') + +# Translators: this is the spoken representation for the character '∝' (U+221d) +_operators['\u221d'] = C_('math symbol', 'proportional to') + +# Translators: this is the spoken representation for the character '∞' (U+221e) +_operators['\u221e'] = C_('math symbol', 'infinity') + +# Translators: this is the spoken representation for the character '∟' (U+221f) +_operators['\u221f'] = C_('math symbol', 'right angle') + +# Translators: this is the spoken representation for the character '∠' (U+2220) +_operators['\u2220'] = C_('math symbol', 'angle') + +# Translators: this is the spoken representation for the character '∡' (U+2221) +_operators['\u2221'] = C_('math symbol', 'measured angle') + +# Translators: this is the spoken representation for the character '∢' (U+2222) +_operators['\u2222'] = C_('math symbol', 'spherical angle') + +# Translators: this is the spoken representation for the character '∣' (U+2223) +_operators['\u2223'] = C_('math symbol', 'divides') + +# Translators: this is the spoken representation for the character '∤' (U+2224) +_operators['\u2224'] = C_('math symbol', 'does not divide') + +# Translators: this is the spoken representation for the character '∥' (U+2225) +_operators['\u2225'] = C_('math symbol', 'parallel to') + +# Translators: this is the spoken representation for the character '∦' (U+2226) +_operators['\u2226'] = C_('math symbol', 'not parallel to') + +# Translators: this is the spoken representation for the character '∧' (U+2227) +_operators['\u2227'] = C_('math symbol', 'logical and') + +# Translators: this is the spoken representation for the character '∨' (U+2228) +_operators['\u2228'] = C_('math symbol', 'logical or') + +# Translators: this is the spoken representation for the character '∩' (U+2229) +_operators['\u2229'] = C_('math symbol', 'intersection') + +# Translators: this is the spoken representation for the character '∪' (U+222a) +_operators['\u222a'] = C_('math symbol', 'union') + +# Translators: this is the spoken representation for the character '∫' (U+222b) +_operators['\u222b'] = C_('math symbol', 'integral') + +# Translators: this is the spoken representation for the character '∬' (U+222c) +_operators['\u222c'] = C_('math symbol', 'double integral') + +# Translators: this is the spoken representation for the character '∭' (U+222d) +_operators['\u222d'] = C_('math symbol', 'triple integral') + +# Translators: this is the spoken representation for the character '∮' (U+222e) +_operators['\u222e'] = C_('math symbol', 'contour integral') + +# Translators: this is the spoken representation for the character '∯' (U+222f) +_operators['\u222f'] = C_('math symbol', 'surface integral') + +# Translators: this is the spoken representation for the character '∰' (U+2230) +_operators['\u2230'] = C_('math symbol', 'volume integral') + +# Translators: this is the spoken representation for the character '∱' (U+2231) +_operators['\u2231'] = C_('math symbol', 'clockwise integral') + +# Translators: this is the spoken representation for the character '∲' (U+2232) +_operators['\u2232'] = C_('math symbol', 'clockwise contour integral') + +# Translators: this is the spoken representation for the character '∳' (U+2233) +_operators['\u2233'] = C_('math symbol', 'anticlockwise contour integral') + +# Translators: this is the spoken representation for the character '∴' (U+2234) +_operators['\u2234'] = C_('math symbol', 'therefore') + +# Translators: this is the spoken representation for the character '∵' (U+2235) +_operators['\u2235'] = C_('math symbol', 'because') + +# Translators: this is the spoken representation for the character '∶' (U+2236) +_operators['\u2236'] = C_('math symbol', 'ratio') + +# Translators: this is the spoken representation for the character '∷' (U+2237) +_operators['\u2237'] = C_('math symbol', 'proportion') + +# Translators: this is the spoken representation for the character '∸' (U+2238) +_operators['\u2238'] = C_('math symbol', 'dot minus') + +# Translators: this is the spoken representation for the character '∹' (U+2239) +_operators['\u2239'] = C_('math symbol', 'excess') + +# Translators: this is the spoken representation for the character '∺' (U+223a) +_operators['\u223a'] = C_('math symbol', 'geometric proportion') + +# Translators: this is the spoken representation for the character '∻' (U+223b) +_operators['\u223b'] = C_('math symbol', 'homothetic') + +# Translators: this is the spoken representation for the character '∼' (U+223c) +_operators['\u223c'] = C_('math symbol', 'tilde') + +# Translators: this is the spoken representation for the character '∽' (U+223d) +_operators['\u223d'] = C_('math symbol', 'reversed tilde') + +# Translators: this is the spoken representation for the character '∾' (U+223e) +_operators['\u223e'] = C_('math symbol', 'inverted lazy S') + +# Translators: this is the spoken representation for the character '∿' (U+223f) +_operators['\u223f'] = C_('math symbol', 'sine wave') + +# Translators: this is the spoken representation for the character '≀' (U+2240) +_operators['\u2240'] = C_('math symbol', 'wreath product') + +# Translators: this is the spoken representation for the character '≁' (U+2241) +_operators['\u2241'] = C_('math symbol', 'not tilde') + +# Translators: this is the spoken representation for the character '≂' (U+2242) +_operators['\u2242'] = C_('math symbol', 'minus tilde') + +# Translators: this is the spoken representation for the character '≃' (U+2243) +_operators['\u2243'] = C_('math symbol', 'asymptotically equal to') + +# Translators: this is the spoken representation for the character '≄' (U+2244) +_operators['\u2244'] = C_('math symbol', 'not asymptotically equal to') + +# Translators: this is the spoken representation for the character '≅' (U+2245) +_operators['\u2245'] = C_('math symbol', 'approximately equal to') + +# Translators: this is the spoken representation for the character '≆' (U+2246) +_operators['\u2246'] = C_('math symbol', 'approximately but not actually equal to') + +# Translators: this is the spoken representation for the character '≇' (U+2247) +_operators['\u2247'] = C_('math symbol', 'neither approximately nor actually equal to') + +# Translators: this is the spoken representation for the character '≈' (U+2248) +_operators['\u2248'] = C_('math symbol', 'almost equal to') + +# Translators: this is the spoken representation for the character '≉' (U+2249) +_operators['\u2249'] = C_('math symbol', 'not almost equal to') + +# Translators: this is the spoken representation for the character '≊' (U+224a) +_operators['\u224a'] = C_('math symbol', 'almost equal or equal to') + +# Translators: this is the spoken representation for the character '≋' (U+224b) +_operators['\u224b'] = C_('math symbol', 'triple tilde') + +# Translators: this is the spoken representation for the character '≌' (U+224c) +_operators['\u224c'] = C_('math symbol', 'all equal to') + +# Translators: this is the spoken representation for the character '≍' (U+224d) +_operators['\u224d'] = C_('math symbol', 'equivalent to') + +# Translators: this is the spoken representation for the character '≎' (U+224e) +_operators['\u224e'] = C_('math symbol', 'geometrically equivalent to') + +# Translators: this is the spoken representation for the character '≏' (U+224f) +_operators['\u224f'] = C_('math symbol', 'difference between') + +# Translators: this is the spoken representation for the character '≐' (U+2250) +_operators['\u2250'] = C_('math symbol', 'approaches the limit') + +# Translators: this is the spoken representation for the character '≑' (U+2251) +_operators['\u2251'] = C_('math symbol', 'geometrically equal to') + +# Translators: this is the spoken representation for the character '≒' (U+2252) +_operators['\u2252'] = C_('math symbol', 'approximately equal to or the image of') + +# Translators: this is the spoken representation for the character '≓' (U+2253) +_operators['\u2253'] = C_('math symbol', 'image of or approximately equal to') + +# Translators: this is the spoken representation for the character '≔' (U+2254) +_operators['\u2254'] = C_('math symbol', 'colon equals') + +# Translators: this is the spoken representation for the character '≕' (U+2255) +_operators['\u2255'] = C_('math symbol', 'equals colon') + +# Translators: this is the spoken representation for the character '≖' (U+2256) +_operators['\u2256'] = C_('math symbol', 'ring in equal to') + +# Translators: this is the spoken representation for the character '≗' (U+2257) +_operators['\u2257'] = C_('math symbol', 'ring equal to') + +# Translators: this is the spoken representation for the character '≘' (U+2258) +_operators['\u2258'] = C_('math symbol', 'corresponds to') + +# Translators: this is the spoken representation for the character '≙' (U+2259) +_operators['\u2259'] = C_('math symbol', 'estimates') + +# Translators: this is the spoken representation for the character '≚' (U+225a) +_operators['\u225a'] = C_('math symbol', 'equiangular to') + +# Translators: this is the spoken representation for the character '≛' (U+225b) +_operators['\u225b'] = C_('math symbol', 'star equals') + +# Translators: this is the spoken representation for the character '≜' (U+225c) +_operators['\u225c'] = C_('math symbol', 'delta equal to') + +# Translators: this is the spoken representation for the character '≝' (U+225d) +_operators['\u225d'] = C_('math symbol', 'equal to by definition') + +# Translators: this is the spoken representation for the character '≞' (U+225e) +_operators['\u225e'] = C_('math symbol', 'measured by') + +# Translators: this is the spoken representation for the character '≟' (U+225f) +_operators['\u225f'] = C_('math symbol', 'questioned equal to') + +# Translators: this is the spoken representation for the character '≠' (U+2260) +_operators['\u2260'] = C_('math symbol', 'not equal to') + +# Translators: this is the spoken representation for the character '≡' (U+2261) +_operators['\u2261'] = C_('math symbol', 'identical to') + +# Translators: this is the spoken representation for the character '≢' (U+2262) +_operators['\u2262'] = C_('math symbol', 'not identical to') + +# Translators: this is the spoken representation for the character '≣' (U+2263) +_operators['\u2263'] = C_('math symbol', 'strictly equivalent to') + +# Translators: this is the spoken representation for the character '≤' (U+2264) +_operators['\u2264'] = C_('math symbol', 'less than or equal to') + +# Translators: this is the spoken representation for the character '≥' (U+2265) +_operators['\u2265'] = C_('math symbol', 'greater than or equal to') + +# Translators: this is the spoken representation for the character '≦' (U+2266) +_operators['\u2266'] = C_('math symbol', 'less than over equal to') + +# Translators: this is the spoken representation for the character '≧' (U+2267) +_operators['\u2267'] = C_('math symbol', 'greater than over equal to') + +# Translators: this is the spoken representation for the character '≨' (U+2268) +_operators['\u2268'] = C_('math symbol', 'less than but not equal to') + +# Translators: this is the spoken representation for the character '≩' (U+2269) +_operators['\u2269'] = C_('math symbol', 'greater than but not equal to') + +# Translators: this is the spoken representation for the character '≪' (U+226a) +_operators['\u226a'] = C_('math symbol', 'much less than') + +# Translators: this is the spoken representation for the character '≫' (U+226b) +_operators['\u226b'] = C_('math symbol', 'much greater than') + +# Translators: this is the spoken representation for the character '≬' (U+226c) +_operators['\u226c'] = C_('math symbol', 'between') + +# Translators: this is the spoken representation for the character '≭' (U+226d) +_operators['\u226d'] = C_('math symbol', 'not equivalent to') + +# Translators: this is the spoken representation for the character '≮' (U+226e) +_operators['\u226e'] = C_('math symbol', 'not less than') + +# Translators: this is the spoken representation for the character '≯' (U+226f) +_operators['\u226f'] = C_('math symbol', 'not greater than') + +# Translators: this is the spoken representation for the character '≰' (U+2270) +_operators['\u2270'] = C_('math symbol', 'neither less than nor equal to') + +# Translators: this is the spoken representation for the character '≱' (U+2271) +_operators['\u2271'] = C_('math symbol', 'neither greater than nor equal to') + +# Translators: this is the spoken representation for the character '≲' (U+2272) +_operators['\u2272'] = C_('math symbol', 'less than or equivalent to') + +# Translators: this is the spoken representation for the character '≳' (U+2273) +_operators['\u2273'] = C_('math symbol', 'greater than or equivalent to') + +# Translators: this is the spoken representation for the character '≴' (U+2274) +_operators['\u2274'] = C_('math symbol', 'neither less than nor equivalent to') + +# Translators: this is the spoken representation for the character '≵' (U+2275) +_operators['\u2275'] = C_('math symbol', 'neither greater than nor equivalent to') + +# Translators: this is the spoken representation for the character '≶' (U+2276) +_operators['\u2276'] = C_('math symbol', 'less than or greater than') + +# Translators: this is the spoken representation for the character '≷' (U+2277) +_operators['\u2277'] = C_('math symbol', 'greater than or less than') + +# Translators: this is the spoken representation for the character '≸' (U+2278) +_operators['\u2278'] = C_('math symbol', 'neither less than nor greater than') + +# Translators: this is the spoken representation for the character '≹' (U+2279) +_operators['\u2279'] = C_('math symbol', 'neither greater than nor less than') + +# Translators: this is the spoken representation for the character '≺' (U+227a) +_operators['\u227a'] = C_('math symbol', 'precedes') + +# Translators: this is the spoken representation for the character '≻' (U+227b) +_operators['\u227b'] = C_('math symbol', 'succeeds') + +# Translators: this is the spoken representation for the character '≼' (U+227c) +_operators['\u227c'] = C_('math symbol', 'precedes or equal to') + +# Translators: this is the spoken representation for the character '≽' (U+227d) +_operators['\u227d'] = C_('math symbol', 'succeeds or equal to') + +# Translators: this is the spoken representation for the character '≾' (U+227e) +_operators['\u227e'] = C_('math symbol', 'precedes or equivalent to') + +# Translators: this is the spoken representation for the character '≿' (U+227f) +_operators['\u227f'] = C_('math symbol', 'succeeds or equivalent to') + +# Translators: this is the spoken representation for the character '⊀' (U+2280) +_operators['\u2280'] = C_('math symbol', 'does not precede') + +# Translators: this is the spoken representation for the character '⊁' (U+2281) +_operators['\u2281'] = C_('math symbol', 'does not succeed') + +# Translators: this is the spoken representation for the character '⊂' (U+2282) +_operators['\u2282'] = C_('math symbol', 'subset of') + +# Translators: this is the spoken representation for the character '⊃' (U+2283) +_operators['\u2283'] = C_('math symbol', 'superset of') + +# Translators: this is the spoken representation for the character '⊄' (U+2284) +_operators['\u2284'] = C_('math symbol', 'not a subset of') + +# Translators: this is the spoken representation for the character '⊅' (U+2285) +_operators['\u2285'] = C_('math symbol', 'not a superset of') + +# Translators: this is the spoken representation for the character '⊆' (U+2286) +_operators['\u2286'] = C_('math symbol', 'subset of or equal to') + +# Translators: this is the spoken representation for the character '⊇' (U+2287) +_operators['\u2287'] = C_('math symbol', 'superset of or equal to') + +# Translators: this is the spoken representation for the character '⊈' (U+2288) +_operators['\u2288'] = C_('math symbol', 'neither a subset of nor equal to') + +# Translators: this is the spoken representation for the character '⊉' (U+2289) +_operators['\u2289'] = C_('math symbol', 'neither a superset of nor equal to') + +# Translators: this is the spoken representation for the character '⊊' (U+228a) +_operators['\u228a'] = C_('math symbol', 'subset of with not equal to') + +# Translators: this is the spoken representation for the character '⊋' (U+228b) +_operators['\u228b'] = C_('math symbol', 'superset of with not equal to') + +# Translators: this is the spoken representation for the character '⊌' (U+228c) +_operators['\u228c'] = C_('math symbol', 'multiset') + +# Translators: this is the spoken representation for the character '⊍' (U+228d) +_operators['\u228d'] = C_('math symbol', 'multiset multiplication') + +# Translators: this is the spoken representation for the character '⊎' (U+228e) +_operators['\u228e'] = C_('math symbol', 'multiset union') + +# Translators: this is the spoken representation for the character '⊏' (U+228f) +_operators['\u228f'] = C_('math symbol', 'square image of') + +# Translators: this is the spoken representation for the character '⊐' (U+2290) +_operators['\u2290'] = C_('math symbol', 'square original of') + +# Translators: this is the spoken representation for the character '⊑' (U+2291) +_operators['\u2291'] = C_('math symbol', 'square image of or equal to') + +# Translators: this is the spoken representation for the character '⊒' (U+2292) +_operators['\u2292'] = C_('math symbol', 'square original of or equal to') + +# Translators: this is the spoken representation for the character '⊓' (U+2293) +_operators['\u2293'] = C_('math symbol', 'square cap') + +# Translators: this is the spoken representation for the character '⊔' (U+2294) +_operators['\u2294'] = C_('math symbol', 'square cup') + +# Translators: this is the spoken representation for the character '⊕' (U+2295) +_operators['\u2295'] = C_('math symbol', 'circled plus') + +# Translators: this is the spoken representation for the character '⊖' (U+2296) +_operators['\u2296'] = C_('math symbol', 'circled minus') + +# Translators: this is the spoken representation for the character '⊗' (U+2297) +_operators['\u2297'] = C_('math symbol', 'circled times') + +# Translators: this is the spoken representation for the character '⊘' (U+2298) +_operators['\u2298'] = C_('math symbol', 'circled division slash') + +# Translators: this is the spoken representation for the character '⊙' (U+2299) +_operators['\u2299'] = C_('math symbol', 'circled dot operator') + +# Translators: this is the spoken representation for the character '⊚' (U+229a) +_operators['\u229a'] = C_('math symbol', 'circled ring operator') + +# Translators: this is the spoken representation for the character '⊛' (U+229b) +_operators['\u229b'] = C_('math symbol', 'circled asterisk operator') + +# Translators: this is the spoken representation for the character '⊜' (U+229c) +_operators['\u229c'] = C_('math symbol', 'circled equals') + +# Translators: this is the spoken representation for the character '⊝' (U+229d) +_operators['\u229d'] = C_('math symbol', 'circled dash') + +# Translators: this is the spoken representation for the character '⊞' (U+229e) +_operators['\u229e'] = C_('math symbol', 'squared plus') + +# Translators: this is the spoken representation for the character '⊟' (U+229f) +_operators['\u229f'] = C_('math symbol', 'squared minus') + +# Translators: this is the spoken representation for the character '⊠' (U+22a0) +_operators['\u22a0'] = C_('math symbol', 'squared times') + +# Translators: this is the spoken representation for the character '⊡' (U+22a1) +_operators['\u22a1'] = C_('math symbol', 'squared dot operator') + +# Translators: this is the spoken representation for the character '⊢' (U+22a2) +_operators['\u22a2'] = C_('math symbol', 'right tack') + +# Translators: this is the spoken representation for the character '⊣' (U+22a3) +_operators['\u22a3'] = C_('math symbol', 'left tack') + +# Translators: this is the spoken representation for the character '⊤' (U+22a4) +_operators['\u22a4'] = C_('math symbol', 'down tack') + +# Translators: this is the spoken representation for the character '⊥' (U+22a5) +_operators['\u22a5'] = C_('math symbol', 'up tack') + +# Translators: this is the spoken representation for the character '⊦' (U+22a6) +_operators['\u22a6'] = C_('math symbol', 'assertion') + +# Translators: this is the spoken representation for the character '⊧' (U+22a7) +_operators['\u22a7'] = C_('math symbol', 'models') + +# Translators: this is the spoken representation for the character '⊨' (U+22a8) +_operators['\u22a8'] = C_('math symbol', 'true') + +# Translators: this is the spoken representation for the character '⊩' (U+22a9) +_operators['\u22a9'] = C_('math symbol', 'forces') + +# Translators: this is the spoken representation for the character '⊪' (U+22aa) +_operators['\u22aa'] = C_('math symbol', 'triple vertical bar right turnstile') + +# Translators: this is the spoken representation for the character '⊫' (U+22ab) +_operators['\u22ab'] = C_('math symbol', 'double vertical bar double right turnstile') + +# Translators: this is the spoken representation for the character '⊬' (U+22ac) +_operators['\u22ac'] = C_('math symbol', 'does not prove') + +# Translators: this is the spoken representation for the character '⊭' (U+22ad) +_operators['\u22ad'] = C_('math symbol', 'not true') + +# Translators: this is the spoken representation for the character '⊮' (U+22ae) +_operators['\u22ae'] = C_('math symbol', 'does not force') + +# Translators: this is the spoken representation for the character '⊯' (U+22af) +_operators['\u22af'] = C_('math symbol', 'negated double vertical bar double right turnstile') + +# Translators: this is the spoken representation for the character '⊰' (U+22b0) +_operators['\u22b0'] = C_('math symbol', 'precedes under relation') + +# Translators: this is the spoken representation for the character '⊱' (U+22b1) +_operators['\u22b1'] = C_('math symbol', 'succeeds under relation') + +# Translators: this is the spoken representation for the character '⊲' (U+22b2) +_operators['\u22b2'] = C_('math symbol', 'normal subgroup of') + +# Translators: this is the spoken representation for the character '⊳' (U+22b3) +_operators['\u22b3'] = C_('math symbol', 'contains as normal subgroup') + +# Translators: this is the spoken representation for the character '⊴' (U+22b4) +_operators['\u22b4'] = C_('math symbol', 'normal subgroup of or equal to') + +# Translators: this is the spoken representation for the character '⊵' (U+22b5) +_operators['\u22b5'] = C_('math symbol', 'contains as normal subgroup of or equal to') + +# Translators: this is the spoken representation for the character '⊶' (U+22b6) +_operators['\u22b6'] = C_('math symbol', 'original of') + +# Translators: this is the spoken representation for the character '⊷' (U+22b7) +_operators['\u22b7'] = C_('math symbol', 'image of') + +# Translators: this is the spoken representation for the character '⊸' (U+22b8) +_operators['\u22b8'] = C_('math symbol', 'multimap') + +# Translators: this is the spoken representation for the character '⊹' (U+22b9) +_operators['\u22b9'] = C_('math symbol', 'hermitian conjugate matrix') + +# Translators: this is the spoken representation for the character '⊺' (U+22ba) +_operators['\u22ba'] = C_('math symbol', 'intercalate') + +# Translators: this is the spoken representation for the character '⊻' (U+22bb) +_operators['\u22bb'] = C_('math symbol', 'xor') + +# Translators: this is the spoken representation for the character '⊼' (U+22bc) +_operators['\u22bc'] = C_('math symbol', 'nand') + +# Translators: this is the spoken representation for the character '⊽' (U+22bd) +_operators['\u22bd'] = C_('math symbol', 'nor') + +# Translators: this is the spoken representation for the character '⊾' (U+22be) +_operators['\u22be'] = C_('math symbol', 'right angle with arc') + +# Translators: this is the spoken representation for the character '⊿' (U+22bf) +_operators['\u22bf'] = C_('math symbol', 'right triangle') + +# Translators: this is the spoken representation for the character '⋀' (U+22c0) +_operators['\u22c0'] = C_('math symbol', 'logical and') + +# Translators: this is the spoken representation for the character '⋁' (U+22c1) +_operators['\u22c1'] = C_('math symbol', 'logical or') + +# Translators: this is the spoken representation for the character '⋂' (U+22c2) +_operators['\u22c2'] = C_('math symbol', 'intersection') + +# Translators: this is the spoken representation for the character '⋃' (U+22c3) +_operators['\u22c3'] = C_('math symbol', 'union') + +# Translators: this is the spoken representation for the character '⋄' (U+22c4) +_operators['\u22c4'] = C_('math symbol', 'diamond operator') + +# Translators: this is the spoken representation for the character '⋅' (U+22c5) +_operators['\u22c5'] = C_('math symbol', 'dot operator') + +# Translators: this is the spoken representation for the character '⋆' (U+22c6) +_operators['\u22c6'] = C_('math symbol', 'star operator') + +# Translators: this is the spoken representation for the character '⋇' (U+22c7) +_operators['\u22c7'] = C_('math symbol', 'division times') + +# Translators: this is the spoken representation for the character '⋈' (U+22c8) +_operators['\u22c8'] = C_('math symbol', 'bowtie') + +# Translators: this is the spoken representation for the character '⋉' (U+22c9) +_operators['\u22c9'] = C_('math symbol', 'left normal factor semidirect product') + +# Translators: this is the spoken representation for the character '⋊' (U+22ca) +_operators['\u22ca'] = C_('math symbol', 'right normal factor semidirect product') + +# Translators: this is the spoken representation for the character '⋋' (U+22cb) +_operators['\u22cb'] = C_('math symbol', 'left semidirect product') + +# Translators: this is the spoken representation for the character '⋌' (U+22cc) +_operators['\u22cc'] = C_('math symbol', 'right semidirect product') + +# Translators: this is the spoken representation for the character '⋍' (U+22cd) +_operators['\u22cd'] = C_('math symbol', 'reversed tilde equals') + +# Translators: this is the spoken representation for the character '⋎' (U+22ce) +_operators['\u22ce'] = C_('math symbol', 'curly logical or') + +# Translators: this is the spoken representation for the character '⋏' (U+22cf) +_operators['\u22cf'] = C_('math symbol', 'curly logical and') + +# Translators: this is the spoken representation for the character '⋐' (U+22d0) +_operators['\u22d0'] = C_('math symbol', 'double subset') + +# Translators: this is the spoken representation for the character '⋑' (U+22d1) +_operators['\u22d1'] = C_('math symbol', 'double superset') + +# Translators: this is the spoken representation for the character '⋒' (U+22d2) +_operators['\u22d2'] = C_('math symbol', 'double intersection') + +# Translators: this is the spoken representation for the character '⋓' (U+22d3) +_operators['\u22d3'] = C_('math symbol', 'double union') + +# Translators: this is the spoken representation for the character '⋔' (U+22d4) +_operators['\u22d4'] = C_('math symbol', 'pitchfork') + +# Translators: this is the spoken representation for the character '⋕' (U+22d5) +_operators['\u22d5'] = C_('math symbol', 'equal and parallel to') + +# Translators: this is the spoken representation for the character '⋖' (U+22d6) +_operators['\u22d6'] = C_('math symbol', 'less than with dot') + +# Translators: this is the spoken representation for the character '⋗' (U+22d7) +_operators['\u22d7'] = C_('math symbol', 'greater than with dot') + +# Translators: this is the spoken representation for the character '⋘' (U+22d8) +_operators['\u22d8'] = C_('math symbol', 'very much less than') + +# Translators: this is the spoken representation for the character '⋙' (U+22d9) +_operators['\u22d9'] = C_('math symbol', 'very much greater than') + +# Translators: this is the spoken representation for the character '⋚' (U+22da) +_operators['\u22da'] = C_('math symbol', 'less than equal to or greater than') + +# Translators: this is the spoken representation for the character '⋛' (U+22db) +_operators['\u22db'] = C_('math symbol', 'greater than equal to or less than') + +# Translators: this is the spoken representation for the character '⋜' (U+22dc) +_operators['\u22dc'] = C_('math symbol', 'equal to or less than') + +# Translators: this is the spoken representation for the character '⋝' (U+22dd) +_operators['\u22dd'] = C_('math symbol', 'equal to or greater than') + +# Translators: this is the spoken representation for the character '⋝' (U+22de) +_operators['\u22de'] = C_('math symbol', 'equal to or precedes') + +# Translators: this is the spoken representation for the character '⋝' (U+22df) +_operators['\u22df'] = C_('math symbol', 'equal to or succeeds') + +# Translators: this is the spoken representation for the character '⋠' (U+22e0) +_operators['\u22e0'] = C_('math symbol', 'does not precede or equal') + +# Translators: this is the spoken representation for the character '⋡' (U+22e1) +_operators['\u22e1'] = C_('math symbol', 'does not succeed or equal') + +# Translators: this is the spoken representation for the character '⋢' (U+22e2) +_operators['\u22e2'] = C_('math symbol', 'not square image of or equal to') + +# Translators: this is the spoken representation for the character '⋣' (U+22e3) +_operators['\u22e3'] = C_('math symbol', 'not square original of or equal to') + +# Translators: this is the spoken representation for the character '⋤' (U+22e4) +_operators['\u22e4'] = C_('math symbol', 'square image of or not equal to') + +# Translators: this is the spoken representation for the character '⋥' (U+22e5) +_operators['\u22e5'] = C_('math symbol', 'square original of or not equal to') + +# Translators: this is the spoken representation for the character '⋦' (U+22e6) +_operators['\u22e6'] = C_('math symbol', 'less than but not equivalent to') + +# Translators: this is the spoken representation for the character '⋧' (U+22e7) +_operators['\u22e7'] = C_('math symbol', 'greater than but not equivalent to') + +# Translators: this is the spoken representation for the character '⋨' (U+22e8) +_operators['\u22e8'] = C_('math symbol', 'precedes but not equivalent to') + +# Translators: this is the spoken representation for the character '⋩' (U+22e9) +_operators['\u22e9'] = C_('math symbol', 'succeeds but not equivalent to') + +# Translators: this is the spoken representation for the character '⋪' (U+22ea) +_operators['\u22ea'] = C_('math symbol', 'not normal subgroup of') + +# Translators: this is the spoken representation for the character '⋫' (U+22eb) +_operators['\u22eb'] = C_('math symbol', 'does not contain as normal subgroup') + +# Translators: this is the spoken representation for the character '⋬' (U+22ec) +_operators['\u22ec'] = C_('math symbol', 'not normal subgroup of or equal to') + +# Translators: this is the spoken representation for the character '⋭' (U+22ed) +_operators['\u22ed'] = C_('math symbol', 'does not contain as normal subgroup or equal') + +# Translators: this is the spoken representation for the character '⋮' (U+22ee) +_operators['\u22ee'] = C_('math symbol', 'vertical ellipsis') + +# Translators: this is the spoken representation for the character '⋯' (U+22ef) +_operators['\u22ef'] = C_('math symbol', 'midline horizontal ellipsis') + +# Translators: this is the spoken representation for the character '⋰' (U+22f0) +_operators['\u22f0'] = C_('math symbol', 'up right diagonal ellipsis') + +# Translators: this is the spoken representation for the character '⋱' (U+22f1) +_operators['\u22f1'] = C_('math symbol', 'down right diagonal ellipsis') + +# Translators: this is the spoken representation for the character '⋲' (U+22f2) +_operators['\u22f2'] = C_('math symbol', 'element of with long horizontal stroke') + +# Translators: this is the spoken representation for the character '⋳' (U+22f3) +_operators['\u22f3'] = C_('math symbol', + 'element of with vertical bar at end of horizontal stroke') + +# Translators: this is the spoken representation for the character '⋴' (U+22f4) +_operators['\u22f4'] = C_('math symbol', + 'small element of with vertical bar at end of horizontal stroke') + +# Translators: this is the spoken representation for the character '⋵' (U+22f5) +_operators['\u22f5'] = C_('math symbol', 'element of with dot above') + +# Translators: this is the spoken representation for the character '⋶' (U+22f6) +_operators['\u22f6'] = C_('math symbol', 'element of with overbar') + +# Translators: this is the spoken representation for the character '⋷' (U+22f7) +_operators['\u22f7'] = C_('math symbol', 'small element of with overbar') + +# Translators: this is the spoken representation for the character '⋸' (U+22f8) +_operators['\u22f8'] = C_('math symbol', 'element of with underbar') + +# Translators: this is the spoken representation for the character '⋹' (U+22f9) +_operators['\u22f9'] = C_('math symbol', 'element of with two horizontal strokes') + +# Translators: this is the spoken representation for the character '⋺' (U+22fa) +_operators['\u22fa'] = C_('math symbol', 'contains with long horizontal stroke') + +# Translators: this is the spoken representation for the character '⋻' (U+22fb) +_operators['\u22fb'] = C_('math symbol', 'contains with vertical bar at end of horizontal stroke') + +# Translators: this is the spoken representation for the character '⋼' (U+22fc) +_operators['\u22fc'] = C_('math symbol', + 'small contains with vertical bar at end of horizontal stroke') + +# Translators: this is the spoken representation for the character '⋽' (U+22fd) +_operators['\u22fd'] = C_('math symbol', 'contains with overbar') + +# Translators: this is the spoken representation for the character '⋾' (U+22fe) +_operators['\u22fe'] = C_('math symbol', 'small contains with overbar') + +# Translators: this is the spoken representation for the character '⋿' (U+22ff) +_operators['\u22ff'] = C_('math symbol', 'z notation bag membership') + +# Translators: this is the spoken representation for the character '⌈' (U+2308) +_operators['\u2308'] = C_('math symbol', 'left ceiling') + +# Translators: this is the spoken representation for the character '⌉' (U+2309) +_operators['\u2309'] = C_('math symbol', 'right ceiling') + +# Translators: this is the spoken representation for the character '⌊' (U+230a) +_operators['\u230a'] = C_('math symbol', 'left floor') + +# Translators: this is the spoken representation for the character '⌋' (U+230b) +_operators['\u230b'] = C_('math symbol', 'right floor') + +# Translators: this is the spoken representation for the character '⏞' (U+23de) +_operators['\u23de'] = C_('math symbol', 'top brace') + +# Translators: this is the spoken representation for the character '⏟' (U+23df) +_operators['\u23df'] = C_('math symbol', 'bottom brace') + +# Translators: this is the spoken representation for the character '⟨' (U+27e8) +_operators['\u27e8'] = C_('math symbol', 'left angle bracket') + +# Translators: this is the spoken representation for the character '⟩' (U+27e9) +_operators['\u27e9'] = C_('math symbol', 'right angle bracket') + +# Translators: this is the spoken representation for the character '⨀' (U+2a00) +_operators['\u2a00'] = C_('math symbol', 'circled dot') + +# Translators: this is the spoken representation for the character '⨁' (U+2a01) +_operators['\u2a01'] = C_('math symbol', 'circled plus') + +# Translators: this is the spoken representation for the character '⨂' (U+2a02) +_operators['\u2a02'] = C_('math symbol', 'circled times') +# Translators: this is the spoken representation for the character '⨃' (U+2a03) +_operators['\u2a03'] = C_('math symbol', 'union with dot') +# Translators: this is the spoken representation for the character '⨄' (U+2a04) +_operators['\u2a04'] = C_('math symbol', 'union with plus') +# Translators: this is the spoken representation for the character '⨅' (U+2a05) +_operators['\u2a05'] = C_('math symbol', 'square intersection') +# Translators: this is the spoken representation for the character '⨆' (U+2a06) +_operators['\u2a06'] = C_('math symbol', 'square union') + +# Translators: this is the spoken representation for the character '■' (U+25a0) +# when used as a geometric shape (i.e. as opposed to a bullet in a list). +_shapes['\u25a0'] = C_('math symbol', 'black square') + +# Translators: this is the spoken representation for the character '□' (U+25a1) +# when used as a geometric shape (i.e. as opposed to a bullet in a list). +_shapes['\u25a1'] = C_('math symbol', 'white square') + +# Translators: this is the spoken representation for the character '◆' (U+25c6) +# when used as a geometric shape (i.e. as opposed to a bullet in a list). +_shapes['\u25c6'] = C_('math symbol', 'black diamond') + +# Translators: this is the spoken representation for the character '○' (U+25cb) +# when used as a geometric shape (i.e. as opposed to a bullet in a list). +_shapes['\u25cb'] = C_('math symbol', 'white circle') + +# Translators: this is the spoken representation for the character '●' (U+25cf) +# when used as a geometric shape (i.e. as opposed to a bullet in a list). +_shapes['\u25cf'] = C_('math symbol', 'black circle') + +# Translators: this is the spoken representation for the character '◦' (U+25e6) +_shapes['\u25e6'] = C_('math symbol', 'white bullet') + +# Translators: this is the spoken representation for the character '◾' (U+25fe) +# when used as a geometric shape (i.e. as opposed to a bullet in a list). +_shapes['\u25fe'] = C_('math symbol', 'black medium small square') + +# Translators: this is the spoken representation for the character '̱' (U+0331) +# which combines with the preceding character. '%s' is a placeholder for the +# preceding character. Some examples of combined symbols can be seen in this +# table: http://www.w3.org/TR/MathML3/appendixc.html#oper-dict.entries-table. +_combining['\u0331'] = C_('math symbol', '%s with underline') + +# Translators: this is the spoken representation for the character '̸' (U+0338) +# which combines with the preceding character. '%s' is a placeholder for the +# preceding character. Some examples of combined symbols can be seen in this +# table: http://www.w3.org/TR/MathML3/appendixc.html#oper-dict.entries-table. +_combining['\u0338'] = C_('math symbol', '%s with slash') + +# Translators: this is the spoken representation for the character '⃒' (U+20D2) +# which combines with the preceding character. '%s' is a placeholder for the +# preceding character. Some examples of combined symbols can be seen in this +# table: http://www.w3.org/TR/MathML3/appendixc.html#oper-dict.entries-table. +_combining['\u20D2'] = C_('math symbol', '%s with vertical line') + +_all.update(_alnum) +_all.update(_arrows) +_all.update(_operators) +_all.update(_shapes) +_RE = None +_RE_COMBINING = None + +def __compileRE(): + global _RE + try: + _RE = re.compile(f"[{''.join(list(_all.keys()))}]", re.UNICODE) + except Exception: + _RE = None + +def __compileRE_COMBINING(): + global _RE_COMBINING + try: + _RE_COMBINING = re.compile(f".[{''.join(list(_combining.keys()))}]", + re.UNICODE) + except Exception: + _RE_COMBINING = None + +def _getStyleString(symbol): + o = ord(symbol) + if o in _bold or o in _boldGreek or o in _boldDigits: + return BOLD + if o in _italic or o in _italicGreek or o in _otherItalic: + return ITALIC + if o in _boldItalic or o in _boldItalicGreek: + return BOLD_ITALIC + if o in _script or o in _otherScript: + return SCRIPT + if o in _boldScript: + return BOLD_SCRIPT + if o in _fraktur or o in _otherFraktur: + return FRAKTUR + if o in _doubleStruck or o in _doubleStruckDigits or o in _otherDoubleStruck: + return DOUBLE_STRUCK + if o in _boldFraktur: + return BOLD_FRAKTUR + if o in _sansSerif or o in _sansSerifDigits: + return SANS_SERIF + if o in _sansSerifBold or o in _sansSerifBoldGreek or o in _sansSerifBoldDigits: + return SANS_SERIF_BOLD + if o in _sansSerifItalic: + return SANS_SERIF_ITALIC + if o in _sansSerifBoldItalic or o in _sansSerifBoldItalicGreek: + return SANS_SERIF_BOLD_ITALIC + if o in _monospace or o in _monospaceDigits: + return MONOSPACE + if o in _dotless: + return DOTLESS + + return "%s" + +def updateSymbols(symbolDict): + global _all + _all.update(symbolDict) + +def _getSpokenName(symbol, includeStyle): + if symbol not in _all: + return "" + + name = _all.get(symbol) + if not name and fallbackOnUnicodeData: + name = unicodedata.name(symbol).lower() + updateSymbols({symbol: name}) + return name + + if includeStyle and symbol in _alnum: + name = _getStyleString(symbol) % name + + return name + +def getCharacterName(symbol): + return _getSpokenName(symbol, speakStyle != SPEAK_NEVER) + +def adjustForSpeech(string): + if _RE is None: + __compileRE() + + if _RE_COMBINING is None: + __compileRE_COMBINING() + + if _RE_COMBINING is not None: + combiningPairs = set(re.findall(_RE_COMBINING, string)) + for pair in combiningPairs: + name = _combining.get(pair[1]) + if name: + string = re.sub(pair, f" {name % pair[0]} ", string) + + if _RE is not None: + chars = set(re.findall(_RE, string)) + includeStyle = speakStyle == SPEAK_ALWAYS + for char in chars: + name = _getSpokenName(char, includeStyle) + if name: + string = re.sub(char, f" {name} ", string) + + return string diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/messages.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/messages.py new file mode 100644 index 0000000..2187fad --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/messages.py @@ -0,0 +1,2865 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Messages which Cthulhu presents in speech and/or braille. These +have been put in their own module so that we can present them in +the correct language when users change the synthesizer language +on the fly without having to reload a bunch of modules.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team" +__license__ = "LGPL" + +from .cthulhu_i18n import _, C_, ngettext +from .cthulhu_platform import version + +# Translators: Sometimes when we attempt to get the name of an accessible +# software application, we fail because the app or one of its elements is +# defunct. This is a generic name so that we can still refer to this element +# in messages. +APPLICATION_NO_NAME = C_("generic name", "application") + +# Translators: This is presented when the user has navigated to an empty line. +BLANK = _("blank") + +# Translators: This refers to font weight. +BOLD = _("bold") + +# Translators: Cthulhu has a feature in which users can store/save a particular +# location in an application window and return to it later by pressing a +# keystroke. These stored/saved locations are "bookmarks". This string is +# presented to the user when a new bookmark has been entered into the list +# of bookmarks. +BOOKMARK_ENTERED = _("bookmark entered") + +# Translators: Cthulhu has a feature in which users can store/save a particular +# location in an application window and return to it later by pressing a +# keystroke. These stored/saved locations are "bookmarks". This string is +# presented to the user when the active list of bookmarks have been saved to +# disk. +BOOKMARKS_SAVED = _("bookmarks saved") + +# Translators: Cthulhu has a feature in which users can store/save a particular +# location in an application window and return to it later by pressing a +# keystroke. These stored/saved locations are "bookmarks". This string is +# presented to the user when an error was encountered, preventing the active +# list of bookmarks being saved to disk. +BOOKMARKS_SAVED_FAILURE = _("bookmarks could not be saved") + +# Translators: Cthulhu has a feature in which users can store/save a particular +# location in an application window and return to it later by pressing a +# keystroke. These stored/saved locations are "bookmarks". This string is +# presented to the user when they try to go to a bookmark, but don't have +# any bookmarks. +BOOKMARKS_NOT_FOUND = _("No bookmarks found.") + +# Translators: Cthulhu has a feature in which users can store/save a particular +# location in an application window and return to it later by pressing a +# keystroke. These stored/saved locations are "bookmarks". This string is +# presented to the user when they try to go to a bookmark at a particular +# index (e.g. bookmark 1 or bookmark 2) but there is no bookmark stored at +# that index. +BOOKMARK_NOT_FOUND = _("Bookmark not found.") + +# Translators: Cthulhu normally intercepts all keyboard commands and only passes +# them along to the current application when they are not Cthulhu commands. This +# command causes the next command issued to be passed along to the current +# application, bypassing Cthulhu's interception of it. +BYPASS_MODE_ENABLED = _("Bypass mode enabled.") + +# Translators: this is an indication that Cthulhu is unable to obtain the display/ +# results area of the calculator being used (e.g. gcalctool). +CALCULATOR_DISPLAY_NOT_FOUND = _("Unable to get calculator display") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter, or play a tone which Speech Dispatcher refers +# to as a sound 'icon'. This string to be translated refers to the brief/ +# non-verbose output presented in response to the use of an Cthulhu command which +# makes it possible for users to quickly cycle amongst these alternatives +# without having to get into a GUI. +CAPITALIZATION_ICON_BRIEF = C_("capitalization style", "icon") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter, or play a tone which Speech Dispatcher refers +# to as a sound 'icon'. This string to be translated refers to the full/verbose +# output presented in response to the use of an Cthulhu command which makes it +# possible for users to quickly cycle amongst these alternatives without having +# to get into a GUI. +CAPITALIZATION_ICON_FULL = _("Capitalization style set to icon.") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter, or play a tone which Speech Dispatcher refers +# to as a sound 'icon'. This string to be translated refers to the brief/ +# non-verbose output presented in response to the use of an Cthulhu command which +# makes it possible for users to quickly cycle amongst these alternatives +# without having to get into a GUI. +CAPITALIZATION_NONE_BRIEF = C_("capitalization style", "none") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter, or play a tone which Speech Dispatcher refers +# to as a sound 'icon'. This string to be translated refers to the full/verbose +# output presented in response to the use of an Cthulhu command which makes it +# possible for users to quickly cycle amongst these alternatives without having +# to get into a GUI. +CAPITALIZATION_NONE_FULL = _("Capitalization style set to none.") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter, or play a tone which Speech Dispatcher refers +# to as a sound 'icon'. This string to be translated refers to the brief/ +# non-verbose output presented in response to the use of an Cthulhu command which +# makes it possible for users to quickly cycle amongst these alternatives +# without having to get into a GUI. +CAPITALIZATION_SPELL_BRIEF = C_("capitalization style", "spell") + +# Translators: Cthulhu uses Speech Dispatcher to present content to users via +# text-to-speech. Speech Dispatcher has a feature to control how capital +# letters are presented: Do nothing at all, say the word 'capital' prior to +# presenting a capital letter, or play a tone which Speech Dispatcher refers +# to as a sound 'icon'. This string to be translated refers to the full/verbose +# output presented in response to the use of an Cthulhu command which makes it +# possible for users to quickly cycle amongst these alternatives without having +# to get into a GUI. +CAPITALIZATION_SPELL_FULL = _("Capitalization style set to spell.") + +# Translators: Native application caret navigation does not always work as the +# Cthulhu user wants. As such, Cthulhu offers the user the ability to toggle between +# the application controlling the caret and Cthulhu controlling it. This message +# is presented to indicate that the application's native caret navigation is +# active / not being overridden by Cthulhu. +CARET_CONTROL_APP = _("The application is controlling the caret.") + +# Translators: Gecko native caret navigation is where Firefox (or Thunderbird) +# itself controls how the arrow keys move the caret around HTML content. It's +# often broken, so Cthulhu needs to provide its own support. As such, Cthulhu offers +# the user the ability to toggle which application is controlling the caret. +CARET_CONTROL_CTHULHU = _("Cthulhu is controlling the caret.") + +# Translators: this is the name of a cell in a spreadsheet. +CELL = _("Cell %s") + +# Translators: this message is spoken to announce that a table cell just became +# selected (e.g as a result of navigation via Shift + Arrows). The string +# substitution is the cell name. In the case of a spreadsheet the cell name +# will be something like "B3". +CELL_SELECTED = C_("cell", "%s selected") + +# Translators: this message is spoken to announce that multiple table cells just +# became selected (e.g as a result of navigation via Shift + Arrows). The first +# string substitution is the name of the first cell in the range. The second string +# substitution is for the name of the last cell in the range. An example message +# for Calc would be "A1 through A30 selected". +CELL_RANGE_SELECTED = C_("cell", "%s through %s selected") + +# Translators: this message is spoken to announce that multiple table cells just +# became unselected (e.g as a result of navigation via Shift + Arrows). The first +# string substitution is the name of the first cell in the range. The second string +# substitution is for the name of the last cell in the range. An example message +# for Calc would be "A1 through A30 unselected". +CELL_RANGE_UNSELECTED = C_("cell", "%s through %s unselected") + +# Translators: this message is spoken to announce that a table cell just became +# unselected (e.g as a result of navigation via Shift + Arrows). The string +# substitution is the cell name. In the case of a spreadsheet the cell name +# will be something like "B3". +CELL_UNSELECTED = C_("cell", "%s unselected") + +# Translators: This is the description of command line option '-d, --disable' +# which allows the user to specify an option to disable as Cthulhu is started. +CLI_DISABLE_OPTION = _("Prevent use of option") + +# Translators: this is the description of command line option '-e, --enable' +# which allows the user to specify an option to enable as Cthulhu is started. +CLI_ENABLE_OPTION = _("Force use of option") + +# Translators: This string indicates to the user what should be provided when +# using the '-e, --enable' or '-d, --disable' command line options. +CLI_OPTION = _("OPTION") + +# Translators: This string appears when using 'Cthulhu -h' at the command line. +# It serves as a sort of title and is followed by a detailed list of Cthulhu's +# optional command-line arguments. +CLI_OPTIONAL_ARGUMENTS = _("Optional arguments") + +# Translators: This string appears when using 'Cthulhu -h' at the command line. +# It is followed by a brief list of Cthulhu's optional command-line arguments. +CLI_USAGE = _("Usage: ") + +# Translators: This message is displayed when the user starts Cthulhu from the +# command line and includes an invalid option or argument. After the message, +# the list of invalid items, as typed by the user, is displayed. +CLI_INVALID_OPTIONS = _("The following are not valid: ") + +# Translators: This is the description of command line option '-l, --list-apps' +# which prints the names of running applications which can be seen by assistive +# technologies such as Cthulhu and Accerciser. +CLI_LIST_APPS = _("Print the known running applications") + +# Translators: This is the description of command line option '-p, --profile' +# which allows you to specify a profile to be loaded. A profile stores a group +# of Cthulhu settings configured by the user for a particular purpose, such as a +# 'Spanish' profile which would include Spanish braille and text-to-speech. +# An Cthulhu settings file contains one or more profiles. +CLI_LOAD_PROFILE = _("Load profile") + +# Translators: This message is presented to the user when the specified profile +# could not be loaded. A profile stores a group of Cthulhu settings configured for +# a particular purpose, such as a Spanish profile which would include Spanish +# braille and Spanish text-to-speech. The string substituted in is the user- +# provided profile name. +CLI_LOAD_PROFILE_ERROR = _("Profile could not be loaded: %s") + +# Translators: This message is presented to the user who attempts to launch Cthulhu +# from some other environment than the graphical desktop. +CLI_NO_DESKTOP_ERROR = \ + _("Cannot start Cthulhu because it cannot connect to the Desktop.") + +# Translators: This message is presented to the user who attempts to launch Cthulhu +# but the launch fails due to an error related to the settings manager. +CLI_SETTINGS_MANAGER_ERROR = \ + _("Could not activate the settings manager. Exiting.") + +# Translators: This message is presented to the user when he/she tries to launch +# Cthulhu, but Cthulhu is already running. +CLI_OTHER_CTHULHUS_ERROR = \ + _('Another Cthulhu process is already running for this ' \ + 'session.\nRun “cthulhu --replace” to replace that ' \ + 'process with a new one.') + +# Translators: This string indicates to the user what should be provided when +# using the '-p, --profile' command line option. +CLI_PROFILE_NAME = _("NAME") + +# Translators: This is the description of command line option '-u, --user-prefs' +# that allows you to specify an alternate location from which to load the user +# preferences. +CLI_LOAD_PREFS = _("Use alternate directory for user preferences") + +# Translators: This string indicates to the user what should be provided when +# using the '-u, --user-prefs' command line option. +CLI_PREFS_DIR = _("DIR") + +# Translators: This is the description of command line option '-v, --version' +# which prints the version of Cthulhu. E.g. '1.23.4'. +CLI_VERSION = _("Version of this application") + +# Translators: This is the description of command line option '-r, --replace' +# which tells Cthulhu to replace any existing Cthulhu process that might be running. +CLI_REPLACE = _("Replace a currently running instance of Cthulhu") + +# Translators: this is the description of command line option '-h, --help' +# which lists all the available command line options. +CLI_HELP = _("Show this help message and exit") + +# Translators: This is the description of command line option '--debug' which +# causes debugging output for Cthulhu to be sent to a file. The YYYY-MM-DD-HH:MM:SS +# portion of the string indicates the file name will be formed from the current +# date and time with 'debug' in front and '.out' at the end. The 'debug' and +# '.out' portions of this string should not be translated (i.e. it should always +# start with 'debug' and end with '.out', regardless of the locale.). +CLI_ENABLE_DEBUG = _("Send debug output to debug-YYYY-MM-DD-HH:MM:SS.out") + +# Translators: This is the description of command line option '--debug-file' +# which allows the user to override the default date-based name of the debugging +# output file. +CLI_DEBUG_FILE = _("Send debug output to the specified file") + +# Translators: This string indicates to the user what should be provided when +# using the '--debug-file' command line option. +CLI_DEBUG_FILE_NAME = _("FILE") + +# Translators: This is the description of command line option '-t, --text-setup' +# that will initially display a list of questions in text form, that the user +# will need to answer, before Cthulhu will startup. For this to happen properly, +# Cthulhu will need to be run from a terminal window. +CLI_SETUP = _("Set up user preferences (text version)") + +# Translators: This is the description of command line option '-s, --setup' +# that will place the user in Cthulhu's GUI preferences dialog. +CLI_GUI_SETUP = _("Set up user preferences (GUI version)") + +# Translators: This text is the description displayed when Cthulhu is launched +# from the command line and the help text is displayed. +CLI_EPILOG = _("Report bugs to cthulhu-list@gnome.org.") + +# Translators: Cthulhu normal speaks the text which was just deleted from a +# document via command. Depending on the circumstances, that might be a +# large string. Therefore, if the text which has just been deleted from a +# document matches the clipboard contents, Cthulhu will indicate that fact +# instead of presenting the full string which was just deleted. This message +# is the full/verbose indication. +CLIPBOARD_CUT_FULL = _("Cut selection to clipboard.") + +# Translators: Cthulhu normal speaks the text which was just deleted from a +# document via command. Depending on the circumstances, that might be a +# large string. Therefore, if the text which has just been deleted from a +# document matches the clipboard contents, Cthulhu will indicate that fact +# instead of presenting the full string which was just deleted. This message +# is the brief indication. +CLIPBOARD_CUT_BRIEF = C_("clipboard", "cut") + +# Translators: This message is the detailed message presented when the contents +# of the clipboard have changed and match the current selection. +CLIPBOARD_COPIED_FULL = _("Copied selection to clipboard.") + +# Translators: This message is the brief message presented when the contents +# of the clipboard have changed and match the current selection. +CLIPBOARD_COPIED_BRIEF = C_("clipboard", "copied") + +# Translators: Cthulhu normal speaks the text which was just inserted into a +# document via command. Depending on the circumstances, that might be a +# large string. Therefore, if the text which has just been inserted into a +# document matches the clipboard contents, Cthulhu will indicate that fact +# instead of presenting the full string which was just inserted. This message +# is the full/verbose indication. +CLIPBOARD_PASTED_FULL = _("Pasted contents from clipboard.") + +# Translators: Cthulhu normal speaks the text which was just inserted into a +# document via command. Depending on the circumstances, that might be a +# large string. Therefore, if the text which has just been inserted into a +# document matches the clipboard contents, Cthulhu will indicate that fact +# instead of presenting the full string which was just inserted. This message +# is the brief indication. +CLIPBOARD_PASTED_BRIEF = C_("clipboard", "pasted") + +# Translators: In chat applications, it is often possible to see that a "buddy" +# is typing currently (e.g. via a keyboard icon or status text). Some users like +# to have this typing status announced by Cthulhu; others find that announcement +# unpleasant. Therefore, it is a setting in Cthulhu. This string to be translated +# is presented when the value of the setting is toggled. +CHAT_BUDDY_TYPING_OFF = _("Do not announce when your buddies are typing.") + +# Translators: In chat applications, it is often possible to see that a "buddy" +# is typing currently (e.g. via a keyboard icon or status text). Some users like +# to have this typing status announced by Cthulhu; others find that announcement +# unpleasant. Therefore, it is a setting in Cthulhu. This string to be translated +# is presented when the value of the setting is toggled. +CHAT_BUDDY_TYPING_ON = _("announce when your buddies are typing.") + +# Translators: In chat applications, Cthulhu automatically presents incoming +# messages in speech and braille. If a user is in multiple conversations or +# channels at the same time, it can be confusing to know what room or channel +# a given message came from just from hearing/reading it. This string to be +# translated is presented to the user to clarify where an incoming message +# came from. The name of the chat room is the string substitution. +CHAT_MESSAGE_FROM_ROOM = _("Message from chat room %s") + +# Translators: This message is presented to inform the user that a new chat +# conversation has been added to the existing conversations. The "tab" here +# refers to the tab which contains the label for a GtkNotebook page. The +# label on the tab is the string substitution. +CHAT_NEW_TAB = _("New chat tab %s") + +# Translators: In chat applications, Cthulhu automatically presents incoming +# messages in speech and braille. If a user is in multiple conversations or +# channels at the same time, it can be confusing to know what room or channel +# a given message came from just from hearing/reading it. For this reason, Cthulhu +# has an option to present the name of the room first ("#a11y hello!" +# instead of " hello!"). This string to be translated is presented when +# the value of the setting is toggled. +CHAT_ROOM_NAME_PREFIX_OFF = _("Do not speak chat room name.") + +# Translators: In chat applications, Cthulhu automatically presents incoming +# messages in speech and braille. If a user is in multiple conversations or +# channels at the same time, it can be confusing to know what room or channel +# a given message came from just from hearing/reading it. For this reason, Cthulhu +# has an option to present the name of the room first ("#a11y hello!" +# instead of " hello!"). This string to be translated is presented when +# the value of the setting is toggled. +CHAT_ROOM_NAME_PREFIX_ON = _("speak chat room name.") + +# Translators: Cthulhu has a command to review previous chat room messages in +# speech and braille. Some users prefer to have this message history combined +# (e.g. the last ten messages which came in, no matter what room they came +# from). Other users prefer to have specific room history (e.g. the last ten +# messages from #a11y). Therefore, this is a setting in Cthulhu. This string to be +# translated is presented when the value of the setting is toggled. +CHAT_SEPARATE_HISTORIES_OFF = \ + _("Do not provide chat room specific message histories.") + +# Translators: Cthulhu has a command to review previous chat room messages in +# speech and braille. Some users prefer to have this message history combined +# (e.g. the last ten messages which came in, no matter what room they came +# from). Other users prefer to have specific room history (e.g. the last ten +# messages from #a11y). Therefore, this is a setting in Cthulhu. This string to be +# translated is presented when the value of the setting is toggled. +CHAT_SEPARATE_HISTORIES_ON = _("Provide chat room specific message histories.") + +DATE_FORMAT_LOCALE = "%x" +DATE_FORMAT_NUMBERS_DM = "%d/%m" +DATE_FORMAT_NUMBERS_MD = "%m/%d" +DATE_FORMAT_NUMBERS_DMY = "%d/%m/%Y" +DATE_FORMAT_NUMBERS_MDY = "%m/%d/%Y" +DATE_FORMAT_NUMBERS_YMD = "%Y/%m/%d" +DATE_FORMAT_FULL_DM = "%A, %-d %B" +DATE_FORMAT_FULL_MD = "%A, %B %-d" +DATE_FORMAT_FULL_DMY = "%A, %-d %B, %Y" +DATE_FORMAT_FULL_MDY = "%A, %B %-d, %Y" +DATE_FORMAT_FULL_YMD = "%Y. %B %-d, %A" +DATE_FORMAT_ABBREVIATED_DM = "%a, %-d %b" +DATE_FORMAT_ABBREVIATED_MD = "%a, %b %-d" +DATE_FORMAT_ABBREVIATED_DMY = "%a, %-d %b, %Y" +DATE_FORMAT_ABBREVIATED_MDY = "%a, %b %-d, %Y" +DATE_FORMAT_ABBREVIATED_YMD = "%Y. %b %-d, %a" + +# Translators: This phrase is spoken to inform the user that what is about to +# be said is content marked for deletion in a document, such as content which +# is inside an HTML 'del' element, or the removed code in a diff. +CONTENT_DELETION_START = C_("content", "deletion start") + +# Translators: This phrase is spoken to inform the user that they have reached +# the end of content marked for deletion in a document, such as content which +# is inside an HTML 'del' element, or the removed code in a diff. +CONTENT_DELETION_END = C_("content", "deletion end") + +# Translators: This phrase is spoken to inform the user that what is about to +# be said is content marked for insertion in a document, such as content which +# is inside an HTML 'ins' element, or the added code in a diff. +CONTENT_INSERTION_START = C_("content", "insertion start") + +# Translators: This phrase is spoken to inform the user that they have reached +# the end of content marked for deletion in a document, such as content which +# is inside an HTML 'ins' element, or the added code in a diff. +CONTENT_INSERTION_END = C_("content", "insertion end") + +# Translators: This phrase is spoken to inform the user that what is about to +# be said is content marked/highlighted in a document, such as content which +# is inside an HTML 'mark' element. +CONTENT_MARK_START = C_("content", "highlight start") + +# Translators: This phrase is spoken to inform the user that they have reached +# the end of content marked/highlighted in a document, such as content which +# is inside an HTML 'mark' element. +CONTENT_MARK_END = C_("content", "highlight end") + +# Translators: This phrase is spoken to inform the user that the content being +# presented is the end of an inline suggestion a document. A "suggestion" is a +# proposed change. This change can include the insertion and/or deletion +# of content, and would typically be seen in a collaborative editor, such as +# in Google Docs. +CONTENT_SUGGESTION_END = C_("content", "suggestion end") + +# Translators: This is for navigating document content by moving to the start +# or end of a container. Examples of containers include tables, lists, and +# blockquotes. When moving to the end of a container, Cthulhu attempts to place +# the caret at the content which follows that container. If this is cannot be +# done (e.g. because the container is the last element on the page), Cthulhu will +# instead present this message as an indication that the container was not +# exited as expected. +CONTAINER_END = _("End of container.") + +# Translators: This is for navigating document content by moving to the start +# or end of a container. Examples of containers include tables, lists, and +# blockquotes. If the user attempts to use this command in an object which is +# not a container, this message will be presented. +CONTAINER_NOT_IN_A = _("Not in a container.") + +# Translators: This message is presented when the user selects all of the items +# in a container that supports selection, such as a GUI table or a list of icons. +CONTAINER_SELECTED_ALL = _("all items selected") + +# Translators: The "default" button in a dialog box is the button that gets +# activated when Enter is pressed anywhere within that dialog box. The string +# substitution is the name of the button (e.g. "OK" or "Close"). +DEFAULT_BUTTON_IS = _("Default button is %s") + +# Translators: The "default" button in a dialog box is the button that gets +# activated when Enter is pressed anywhere within that dialog box. This +# message is presented when the default button was found but is insensitive / +# grayed out / cannot be activated. The string substitution is the name of +# the button (e.g. "OK" or "Close"). When translating "Grayed," please use +# the same word used for the string in object_properties.py. +DEFAULT_BUTTON_IS_GRAYED = _("Default button is %s. Grayed") + +# Translators: The "default" button in a dialog box is the button that gets +# activated when Enter is pressed anywhere within that dialog box. Cthulhu has +# a command to present the default button. This is the message Cthulhu will +# present if it could not find the default button. +DEFAULT_BUTTON_NOT_FOUND = _("Default button not found") + +# Translators: This string is part of the presentation of an item that includes +# one or several consecutive subscripted characters. For example, 'X' followed +# by 'subscript 2' followed by 'subscript 3' should be presented to the user as +# 'X subscript 23'. +DIGITS_SUBSCRIPT = _(" subscript %s") + +# Translators: This string is part of the presentation of an item that includes +# one or several consecutive superscripted characters. For example, 'X' followed +# by 'superscript 2' followed by 'superscript 3' should be presented to the user +# as 'X superscript 23'. +DIGITS_SUPERSCRIPT = _(" superscript %s") + +# Translators: this message is presented when the user tries to perform a command +# specific to dialog boxes, such as presenting the default button, but is not in +# a dialog. +DIALOG_NOT_IN_A = _("Not in a dialog") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects the entire +# document by pressing Ctrl+A. +DOCUMENT_SELECTED_ALL = _("entire document selected") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the entire document had been +# selected but the user presses a key (e.g. an arrow key) causing the +# selection to be completely removed. +DOCUMENT_UNSELECTED_ALL = _("entire document unselected") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the end of the document by pressing Ctrl+Shift+End. +DOCUMENT_SELECTED_DOWN = _("document selected from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects previously +# selected text by pressing Ctrl+Shift+End. +DOCUMENT_UNSELECTED_DOWN = _("document unselected from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the start of the document by pressing Ctrl+Shift+Home. +DOCUMENT_SELECTED_UP = _("document selected to cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects previously +# selected text by pressing Ctrl+Shift+Home. +DOCUMENT_UNSELECTED_UP = _("document unselected to cursor position") + +# Translators: Cthulhu allows you to dynamically define which row of a spreadsheet +# or table should be treated as containing column headers. This message is +# presented when the user sets the row to a particular row number. +DYNAMIC_COLUMN_HEADER_SET = _("Dynamic column header set for row %d") + +# Translators: Cthulhu allows you to dynamically define which row of a spreadsheet +# or table should be treated as containing column headers. This message is +# presented when the user unsets the row so it is no longer treated as if it +# contained column headers. +DYNAMIC_COLUMN_HEADER_CLEARED = _("Dynamic column header cleared.") + +# Translators: Cthulhu allows you to dynamically define which column of a +# spreadsheet or table should be treated as containing column headers. This +# message is presented when the user sets the column to a particular column +# number. +DYNAMIC_ROW_HEADER_SET = _("Dynamic row header set for column %s") + +# Translators: Cthulhu allows you to dynamically define which column of a +# spreadsheet or table should be treated as containing column headers. This +# message is presented when the user unsets the column so it is no longer +# treated as if it contained row headers. +DYNAMIC_ROW_HEADER_CLEARED = _("Dynamic row header cleared.") + +# Translators: this is used to announce that the current input line in a +# spreadsheet is blank/empty. +EMPTY = _("empty") + +# Translators: This is the size of a file in kilobytes +FILE_SIZE_KB = _("%.2f kilobytes") + +# Translators: This is the size of a file in megabytes +FILE_SIZE_MB = _("%.2f megabytes") + +# Translators: This message is presented to the user after performing a file +# search to indicate there were no matches. +FILES_NOT_FOUND = _("No files found.") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know that he/she successfully appended the contents under +# flat review onto the existing contents of the clipboard. +FLAT_REVIEW_APPENDED = _("Appended contents to clipboard.") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know that he/she successfully copied the contents under flat +# review to the clipboard. +FLAT_REVIEW_COPIED = _("Copied contents to clipboard.") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know that he/she attempted to use a flat review command when +# not using flat review. +FLAT_REVIEW_NOT_IN = _("Not using flat review.") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know he/she just entered flat review. +FLAT_REVIEW_START = _("Entering flat review.") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know he/she just entered flat review. +FLAT_REVIEW_STOP = _("Leaving flat review.") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know that flat review is being restricted to the current +# object of interest. +FLAT_REVIEW_RESTRICTED = _("Flat review restricted to the current object") + +# Translators: the 'flat review' feature of Cthulhu allows the blind user to +# explore the text in a window in a 2D fashion. That is, Cthulhu treats all +# the text from all objects in a window (e.g., buttons, labels, etc.) as a +# sequence of words in a sequence of lines. This message is presented to +# let the user know that flat review is unrestricted, +# that is, the entire window can be explored. +FLAT_REVIEW_UNRESTRICTED = _("Flat review unrestricted") + +# Translators: this means a particular cell in a spreadsheet has a formula +# (e.g., "=sum(a1:d1)") +HAS_FORMULA = _("has formula") + +# Translators: this message will be presented to indicate the focused object +# will cause a dialog to appear if activated. +HAS_POPUP_DIALOG = _("opens dialog") + +# Translators: this message will be presented to indicate the focused object +# will cause a grid to appear if activated. A grid is an interactive table. +HAS_POPUP_GRID = _("opens grid") + +# Translators: this message will be presented to indicate the focused object +# will cause a listbox to appear if activated. +HAS_POPUP_LISTBOX = _("opens listbox") + +# Translators: this message will be presented to indicate the focused object +# will cause a menu to appear if activated. +HAS_POPUP_MENU = _("opens menu") + +# Translators: this message will be presented to indicate the focused object +# will cause a tree to appear if activated. A tree is a list with sub-levels +# which can be expanded or collapsed, similar to the list of folders in an +# email client. +HAS_POPUP_TREE = _("opens tree") + +# Translators: The following string is spoken to let the user know that he/she +# is on a link within an image map. An image map is an image/graphic which has +# been divided into regions. Each region can be clicked on and has an associated +# link. Please see http://en.wikipedia.org/wiki/Imagemap for more information +# and examples. +IMAGE_MAP_LINK = _("image map link") + +# Translators: This is a spoken and/or brailled message letting the user know +# that the key combination (e.g., Ctrl+Alt+f) they just entered has already been +# bound to another command and is thus unavailable. The string substituted in is +# the name of the command which already has the binding. +KB_ALREADY_BOUND = _("The key entered is already bound to %s") + +# Translators: This is a spoken and/or brailled message letting the user know +# that Cthulhu has recorded a new key combination (e.g. Alt+Ctrl+g) as a result of +# their input. The string substituted in is the new key combination. +KB_CAPTURED = _("Key captured: %s. Press enter to confirm.") + +# Translators: This is a spoken and/or brailled message letting the user know +# that Cthulhu has assigned a new key combination (e.g. Alt+Ctrl+g) as a result of +# their input. The string substituted in is the new key combination. +KB_CAPTURED_CONFIRMATION = _("The new key is: %s") + +# Translators: This is a spoken and/or brailled message letting the user know +# Cthulhu is about to delete an existing key combination (e.g. Alt+Ctrl+g) as a +# result of their input. +KB_DELETED = _("Key binding deleted. Press enter to confirm.") + +# Translators: This is a spoken and/or brailled message letting the user know +# Cthulhu has deleted an existing key combination (e.g. Alt+Ctrl+g) as a result of +# their input. +KB_DELETED_CONFIRMATION = _("The keybinding has been removed.") + +# Translators: This is a spoken and/or brailled message asking the user to press +# a new key combination (e.g., Alt+Ctrl+g) to create a new key binding for an +# Cthulhu command. +KB_ENTER_NEW_KEY = _("enter new key") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. The +# following string is a brief message which will be presented to the user who +# is cycling amongst the various echo options. +KEY_ECHO_KEY_BRIEF = C_("key echo", "key") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. +KEY_ECHO_KEY_FULL = _("Echo set to key.") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. The +# following string is a brief message which will be presented to the user who +# is cycling amongst the various echo options. +KEY_ECHO_NONE_BRIEF = C_("key echo", "None") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. +KEY_ECHO_NONE_FULL = _("Echo set to None.") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. The +# following string is a brief message which will be presented to the user who +# is cycling amongst the various echo options. +KEY_ECHO_KEY_AND_WORD_BRIEF = C_("key echo", "key and word") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. +KEY_ECHO_KEY_AND_WORD_FULL = _("Echo set to key and word.") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. The +# following string is a brief message which will be presented to the user who +# is cycling amongst the various echo options. +KEY_ECHO_SENTENCE_BRIEF = C_("key echo", "sentence") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. +KEY_ECHO_SENTENCE_FULL = _("Echo set to sentence.") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. The +# following string is a brief message which will be presented to the user who +# is cycling amongst the various echo options. +KEY_ECHO_WORD_BRIEF = C_("key echo", "word") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. +KEY_ECHO_WORD_FULL = _("Echo set to word.") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. The +# following string is a brief message which will be presented to the user who +# is cycling amongst the various echo options. +KEY_ECHO_WORD_AND_SENTENCE_BRIEF = C_("key echo", "word and sentence") + +# Translators: Cthulhu has an "echo" setting which allows the user to configure +# what is spoken in response to a key press. Given a user who typed "Hello +# world.": +# - key echo: "H e l l o space w o r l d period" +# - word echo: "Hello" spoken when the space is pressed; +# "world" spoken when the period is pressed. +# - sentence echo: "Hello world" spoken when the period +# is pressed. +# A user can choose to have no echo, one type of echo, or multiple types of +# echo and can cycle through the various levels quickly via a command. +KEY_ECHO_WORD_AND_SENTENCE_FULL = _("Echo set to word and sentence.") + +# Translators: This phrase is spoken to inform the user of all of the MathML +# enclosure notations associated with a given mathematical expression. For +# instance, the expression x+y could be enclosed by a box, or enclosed by a +# circle. It could also be enclosed by a box and a circle and long division +# sign and have a line on the left and on the right and a vertical strike. +# (Though let's hope not.) Given that we do not know the enclosures, their +# order, or their combination, we'll present them as a list. The string +# substitution is for that list of enclosure types. For more information +# about the MathML 'menclose' element and its notation types, see: +# http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_ENCLOSED_BY = C_("math enclosure", "Enclosed by: %s") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_ACTUARIAL = C_("math enclosure", "an actuarial symbol") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_BOX = C_("math enclosure", "a box") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_CIRCLE = C_("math enclosure", "a circle") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_LONGDIV = C_("math enclosure", "a long division sign") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_RADICAL = C_("math enclosure", "a radical") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_ROUNDEDBOX = C_("math enclosure", "a rounded box") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_HORIZONTALSTRIKE = C_("math enclosure", "a horizontal strike") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_VERTICALSTRIKE = C_("math enclosure", "a vertical strike") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_DOWNDIAGONALSTRIKE = C_("math enclosure", "a down diagonal strike") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_UPDIAGONALSTRIKE = C_("math enclosure", "an up diagonal strike") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_NORTHEASTARROW = C_("math enclosure", "a northeast arrow") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_BOTTOM = C_("math enclosure", "a line at the bottom") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_LEFT = C_("math enclosure", "a line on the left") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_RIGHT = C_("math enclosure", "a line on the right") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_TOP = C_("math enclosure", "a line at the top") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_PHASOR_ANGLE = C_("math enclosure", "a phasor angle") + +# Translators: This phrase is spoken to describe one MathML enclosure notation +# associated with a mathematical expression. Because an expression, such as +# x+y, can have one or many enclosure notations (box, circle, long division, +# line on the left, vertical strike), we present them as a list of notations. +# For more information about the MathML 'menclose' element and its notation +# types, see: http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +# This particular string is for the "madruwb" notation type. +MATH_ENCLOSURE_MADRUWB = C_("math enclosure", "an arabic factorial symbol") + +# Translators: This phrase is spoken to inform the user of all of the MathML +# enclosure notations associated with a given mathematical expression. For +# instance, the expression x+y could be enclosed by a box, or enclosed by a +# circle. It could also be enclosed by a box and a circle and long division +# sign and have a line on the left and on the right and a vertical strike. +# (Though let's hope not.) Given that we do not know the enclosures, their +# order, or their combination, we'll present them as a list. This string +# will be inserted before the final item in the list if there is more than +# one enclosure notation. For more information about the MathML 'menclose' +# element and its notation types, see: +# http://www.w3.org/TR/MathML3/chapter3.html#presm.menclose +MATH_ENCLOSURE_AND = C_("math enclosure", "and") + +# Translators: This phrase is spoken to inform the user that what is about to +# be said is part of a mathematical fraction. For instance, given x+1/y+2, Cthulhu +# would say "fraction start, x+1 over y+2, fraction end." +MATH_FRACTION_START = _("fraction start") + +# Translators: This phrase is spoken to inform the user that what is about to +# be said is part of a mathematical fraction whose bar is not displayed. See +# https://en.wikipedia.org/wiki/Combination for an example. Note that the +# comma is inserted here to cause a very brief pause in the speech. Otherwise, +# in English, the resulting speech sounds like we have a fraction which lacks +# the start of the bar. If this is a non-issue for your language, the comma and +# the pause which results is not needed. You should be able to test this with +# "spd-say " in a terminal on a machine where speech-dispatcher +# is installed. +MATH_FRACTION_WITHOUT_BAR_START = _("fraction without bar, start") + +# Translators: This word refers to the line separating the numerator from the +# denominator in a mathematical fraction. For instance, given x+1/y+2, Cthulhu +# would would say "fraction start, x+1 over y+2, fraction end." +MATH_FRACTION_LINE = C_("math fraction", "over") + +# Translators: This phrase is spoken to inform the user that the last spoken +# phrase is the end of a mathematical fraction. For instance, given x+1/y+2, +# Cthulhu would would say "fraction start, x+1 over y+2, fraction end." +MATH_FRACTION_END = _("fraction end") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is a square root. For instance, for √9 Cthulhu would say "square root +# of 9, root end" (assuming the user settings indicate that root endings should +# be spoken). Note that the radicand, which follows the "of", is unknown and +# might not even be a simple string; it might be the square root of another +# expression such as a fraction. +MATH_SQUARE_ROOT_OF = _("square root of") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is a cube root. For instance, for the cube root of 9 Cthulhu would +# say "cube root of 9, root end" (assuming the user settings indicate that root +# endings should be spoken). Note that the radicand, which follows the "of", +# is unknown and might not even be a simple string; it might be the cube root +# of another expression such as a fraction. +MATH_CUBE_ROOT_OF = _("cube root of") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is an nth root. https://en.wikipedia.org/wiki/Nth_root. For instance, +# for the fourth root of 9, Cthulhu would say "fourth root of 9, root end" (assuming +# the user settings indicate that root endings should be spoken). Note that the +# index, which precedes this string, is unknown and might not even be a simple +# expression like "fourth"; the index might instead be a fraction. +MATH_ROOT_OF = _("root of") + +# Translators: This phrase is spoken to inform the user that what is about to +# be said is part of a mathematical root (square root, cube root, nth root). +# It is primarily intended to be spoken when the index of the root is not a +# simple expression. For instance, for the fourth root of 9, simply speaking +# "fourth root of 9" may be sufficient for the user. But if the index is not +# 4, but instead the fraction x/4, beginning the phrase with "root start" can +# help the user better understand that x/4 is the index of the root. +MATH_ROOT_START = _("root start") + +# Translators: This phrase is spoken to inform the user that the last spoken +# phrase is the end of a mathematical root (square root, cube root, nth root). +# For instance, for the cube root of 9, Cthulhu would say "cube root of 9, root +# end" (assuming the user settings indicate that root endings should be spoken). +MATH_ROOT_END = _("root end") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is subscripted text in a mathematical expression. Note that the +# subscript might be simple text or may itself be a mathematical expression, +# and in this instance we have no additional context through which a more user- +# friendly word or phrase can reliably be chosen. +MATH_SUBSCRIPT = C_("math script generic", "subscript") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is superscripted text in a mathematical expression. Note that the +# superscript might be simple text or may itself be a mathematical expression, +# and in this instance we have no additional context through which a more user- +# friendly word or phrase can reliably be chosen. +MATH_SUPERSCRIPT = C_("math script generic", "superscript") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is subscripted text which precedes the base in a mathematical +# expression. See, for instance, the MathML mmultiscripts element: +# http://www.w3.org/TR/MathML3/chapter3.html#presm.mmultiscripts +# https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mmultiscripts +MATH_PRE_SUBSCRIPT = C_("math script", "pre-subscript") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is superscripted text which precedes the base in a mathematical +# expression. See, for instance, the MathML mmultiscripts element: +# http://www.w3.org/TR/MathML3/chapter3.html#presm.mmultiscripts +# https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mmultiscripts +MATH_PRE_SUPERSCRIPT = C_("math script", "pre-superscript") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is underscripted text in a mathematical expression. Note that the +# underscript might be simple text or may itself be a mathematical expression, +# and in this instance we have no additional context through which a more user- +# friendly word or phrase can reliably be chosen. Examples of underscripts: +# http://www.w3.org/TR/MathML/chapter3.html#presm.munder +# https://reference.wolfram.com/language/ref/Underscript.html +MATH_UNDERSCRIPT = C_("math script generic", "underscript") + +# Translators: This phrase is spoken to inform the user that what is about to +# be spoken is overscripted text in a mathematical expression. Note that the +# overscript might be simple text or may itself be a mathematical expression, +# and in this instance we have no additional context through which a more user- +# friendly word or phrase can reliably be chosen. Examples of overscripts: +# http://www.w3.org/TR/MathML/chapter3.html#presm.mover +# https://reference.wolfram.com/language/ref/Overscript.html +MATH_OVERSCRIPT = C_("math script generic", "overscript") + +# Translators: This phrase is spoken to inform the user that the last spoken +# phrase is the end of a mathematical table. +MATH_TABLE_END = C_("math table", "table end") + +# Translators: This phrase is spoken to inform the user that the last spoken +# phrase is the end of a mathematical table which is nested inside another +# mathematical table. +MATH_NESTED_TABLE_END = C_("math table", "nested table end") + +# Translators: Inaccessible means that the application cannot be read by Cthulhu. +# This usually means the application is not friendly to the assistive technology +# infrastructure. +INACCESSIBLE = _("inaccessible") + +# Translators: This brief message indicates that indentation and +# justification will be spoken. +INDENTATION_JUSTIFICATION_OFF_BRIEF = \ + C_("indentation and justification", "Disabled") + +# Translators: This detailed message indicates that indentation and +# justification will not be spoken. +INDENTATION_JUSTIFICATION_OFF_FULL = \ + _("Speaking of indentation and justification disabled.") + +# Translators: This brief message indicates that indentation and +# justification will be spoken. +INDENTATION_JUSTIFICATION_ON_BRIEF = \ + C_("indentation and justification", "Enabled") + +# Translators: This detailed message indicates that indentation and +# justification will be spoken. +INDENTATION_JUSTIFICATION_ON_FULL = \ + _("Speaking of indentation and justification enabled.") + +# Translators: Cthulhu has a "Learn Mode" that will allow the user to type any key +# on the keyboard and hear what the effects of that key would be. The effects +# might be what Cthulhu would do if it had a handler for the particular key +# combination, or they might just be to echo the name of the key if Cthulhu doesn't +# have a handler. This message is what is presented on the braille display when +# entering Learn Mode. +LEARN_MODE_START_BRAILLE = _("Learn mode. Press escape to exit.") + +# Translators: Cthulhu has a "Learn Mode" that will allow the user to type any key +# on the keyboard and hear what the effects of that key would be. The effects +# might be what Cthulhu would do if it had a handler for the particular key +# combination, or they might just be to echo the name of the key if Cthulhu doesn't +# have a handler. This message is what is spoken to the user when entering Learn +# Mode. +LEARN_MODE_START_SPEECH = \ + _("Entering learn mode. Press any key to hear its function. " \ + "To view Cthulhu’s documentation, press F1. " \ + "To get a list of Cthulhu’s default shortcuts, press F2. " \ + "To get a list of Cthulhu’s shortcuts for the current application, " \ + "press F3. " \ + "To exit learn mode, press the escape key.") + +# Translators: This message is presented when a user is navigating within a +# blockquote and then navigates out of it. +LEAVING_BLOCKQUOTE = _("leaving blockquote.") + +# Translators: In web content, authors can identify an element which contains +# detailed information about another element. For instance, for a password +# field, there may be a list of requirements (number of characters, number of +# special symbols, etc.). For an image, there may be an extended description +# before or after the image. Often there are visual clues connecting the +# detailed information to its related object. We need to convey this non-visually. +# This message is presented when a user just navigated out of a container holding +# detailed information about another object. +# See https://w3c.github.io/aria/#aria-details +LEAVING_DETAILS = _("leaving details.") + +# Translators: This message is presented when a user is navigating within +# an object and then navigates out of it. The word or phrase that follows +# "leaving" should be consistent with the translation provided for the +# corresponding term with context "role" found in object_properties.py +LEAVING_FEED = C_("role", "leaving feed.") + +# Translators: This message is presented when a user is navigating within +# an object and then navigates out of it. The word or phrase that follows +# "leaving" should be consistent with the translation provided for the +# corresponding term with context "role" found in object_properties.py +LEAVING_FIGURE = C_("role", "leaving figure.") + +# Translators: This message is presented when a user is navigating within a +# form and then navigates out of it. +LEAVING_FORM = _("leaving form.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_BANNER = C_("role", "leaving banner.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_COMPLEMENTARY = C_("role", "leaving complementary content.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_CONTENTINFO = C_("role", "leaving information.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_MAIN = C_("role", "leaving main content.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_NAVIGATION = C_("role", "leaving navigation.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_REGION = C_("role", "leaving region.") + +# Translators: This message is presented when a user is navigating within +# a type of landmark and then navigates out of it. The word or phrase that +# follows "leaving" should be consistent with the translation provided for +# the corresponding term with context "role" found in object_properties.py +LEAVING_LANDMARK_SEARCH = C_("role", "leaving search.") + +# Translators: This message is presented when a user is navigating within a +# list and then navigates out of it. +LEAVING_LIST = _("leaving list.") + +# Translators: This message is presented when a user is navigating within a +# panel and then navigates out of it. A panel is a generic container of +# objects, such as a group of related form fields. +LEAVING_PANEL = _("leaving panel.") + +# Translators: This message is presented when a user is navigating within a +# table and then navigates out of it. +LEAVING_TABLE = _("leaving table.") + +# Translators: This message is presented when a user is navigating within a +# tooltip in a web application and then navigates out of it. +LEAVING_TOOL_TIP = _("leaving tooltip.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_ABSTRACT = C_("role", "leaving abstract.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_ACKNOWLEDGMENTS = C_("role", "leaving acknowledgments.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_AFTERWORD = C_("role", "leaving afterword.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_APPENDIX = C_("role", "leaving appendix.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_BIBLIOGRAPHY = C_("role", "leaving bibliography.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_CHAPTER = C_("role", "leaving chapter.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_COLOPHON = C_("role", "leaving colophon.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_CONCLUSION = C_("role", "leaving conclusion.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_CREDIT = C_("role", "leaving credit.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_CREDITS = C_("role", "leaving credits.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_DEDICATION = C_("role", "leaving dedication.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_ENDNOTES = C_("role", "leaving endnotes.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_EPIGRAPH = C_("role", "leaving epigraph.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_EPILOGUE = C_("role", "leaving epilogue.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_ERRATA = C_("role", "leaving errata.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_EXAMPLE = C_("role", "leaving example.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_FOREWORD = C_("role", "leaving foreword.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_GLOSSARY = C_("role", "leaving glossary.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_INDEX = C_("role", "leaving index.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_INTRODUCTION = C_("role", "leaving introduction.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_PAGELIST = C_("role", "leaving page list.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_PART = C_("role", "leaving part.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_PREFACE = C_("role", "leaving preface.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_PROLOGUE = C_("role", "leaving prologue.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_PULLQUOTE = C_("role", "leaving pullquote.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_QNA = C_("role", "leaving QNA.") + +# Translators: This message is presented when a user is navigating within a +# suggestion and then navigates out of it. A "suggestion" is a container with +# a proposed change. This change can include the insertion and/or deletion +# of content, and would typically be seen in a collaborative editor, such as +# in Google Docs. +LEAVING_SUGGESTION = C_("role", "leaving suggestion.") + +# Translators: This message is presented when a user is navigating within +# a document container and then navigates out of it. The word or phrase +# that follows "leaving" should be consistent with the translation provided +# for the corresponding term with context "role" found in object_properties.py +LEAVING_TOC = C_("role", "leaving table of contents.") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the end of the line by pressing Shift+Down. +LINE_SELECTED_DOWN = _("line selected down from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the start of the line by pressing Shift+Up. +LINE_SELECTED_UP = _("line selected up from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects previously +# selected text from the current location to the end of the paragraph by +# pressing Shift+Down. +LINE_UNSELECTED_DOWN = _("line unselected down from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects previously +# selected text from the current location to the start of the paragraph by +# pressing Shift+Up. +LINE_UNSELECTED_UP = _("line unselected up from cursor position") + +# Translators: Cthulhu has a "Learn Mode" that will allow the user to type any key +# on the keyboard and hear what the effects of that key would be. The effects +# might be what Cthulhu would do if it had a handler for the particular key +# combination, or they might just be to echo the name of the key if Cthulhu doesn't +# have a handler. This message is what is presented in speech and braille when +# exiting Learn Mode. +LEARN_MODE_STOP = _("Exiting learn mode.") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the start of the line by pressing Ctrl+Shift+Page_Up. +LINE_SELECTED_LEFT = _("line selected from start to previous cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the end of the line by pressing Ctrl+Shift+Page_Down. +LINE_SELECTED_RIGHT = _("line selected to end from previous cursor position") + +# Translators: this indicates that this piece of text is a hypertext link. +LINK = _("link") + +# Translators: this is an indication that a given link points to an object +# that is on the same page. +LINK_SAME_PAGE = _("same page") + +# Translators: this is an indication that a given link points to an object +# that is at the same site (but not on the same page as the link). +LINK_SAME_SITE = _("same site") + +# Translators: this is an indication that a given link points to an object +# that is at a different site than that of the link. +LINK_DIFFERENT_SITE = _("different site") + +# Translators: this refers to a link to a file, where the first item is the +# protocol (ftp, ftps, or file) and the second item the name of the file being +# linked to. +LINK_TO_FILE = _("%(uri)s link to %(file)s") + +# Translators: this message conveys the protocol of a link eg. http, mailto. +LINK_WITH_PROTOCOL = _("%s link") + +# Translators: this message conveys the protocol of a link eg. http, mailto. +# along with the visited state of that link. +LINK_WITH_PROTOCOL_VISITED = _("visited %s link") + +# Translators: The following string instructs the user how to navigate amongst +# the list of commands presented in learn mode, as well as how to exit the list +# when finished. +LIST_NAVIGATION = \ + _("Use Up and Down Arrow to navigate the list. Press Escape to exit.") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user that Cthulhu's live region's "politeness" level has changed to +# "off" for all of the live regions. +LIVE_REGIONS_ALL_OFF = _("All live regions set to off") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user that Cthulhu's live region's "politeness" level for all live +# regions has been restored to their original values. +LIVE_REGIONS_ALL_RESTORED = _("live regions politeness levels restored") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user of the "politeness" level for the current live region. +LIVE_REGIONS_LEVEL = _("politeness level %s") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user that Cthulhu's live region's "politeness" level has changed for +# the current live region. +LIVE_REGIONS_LEVEL_ASSERTIVE = _("setting live region to assertive") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user that Cthulhu's live region's "politeness" level has changed for +# the current live region. +LIVE_REGIONS_LEVEL_OFF = _("setting live region to off") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user that Cthulhu's live region's "politeness" level has changed for +# the current live region. +LIVE_REGIONS_LEVEL_POLITE = _("setting live region to polite") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# The "politeness" level is an indication of when the user wishes to be notified +# about a change to live region content. Examples include: never ("off"), when +# idle ("polite"), and when there is a change ("assertive"). Cthulhu has several +# features to facilitate accessing live regions. This message is presented to +# inform the user that Cthulhu's live region's "politeness" level has changed for +# the current live region. +LIVE_REGIONS_LEVEL_RUDE = _("setting live region to rude") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# Cthulhu has several features to facilitate accessing live regions. This message +# is presented in response to a command that toggles whether or not Cthulhu pays +# attention to changes in live regions. Note that turning off monitoring of live +# events is NOT the same as turning the politeness level to "off". The user can +# opt to have no notifications presented (politeness level of "off") and still +# manually review recent updates to live regions via Cthulhu commands for doing so +# -- as long as the monitoring of live regions is enabled. +LIVE_REGIONS_MONITORING_OFF = _("Live regions monitoring off") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# Cthulhu has several features to facilitate accessing live regions. This message +# is presented in response to a command that toggles whether or not Cthulhu pays +# attention to changes in live regions. Note that turning off monitoring of live +# events is NOT the same as turning the politeness level to "off". The user can +# opt to have no notifications presented (politeness level of "off") and still +# manually review recent updates to live regions via Cthulhu commands for doing so +# -- as long as the monitoring of live regions is enabled. +LIVE_REGIONS_MONITORING_ON = _("Live regions monitoring on") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# Cthulhu has several features to facilitate accessing live regions. This message +# is presented to inform the user that a cached message is not available for the +# the current live region. +LIVE_REGIONS_NO_MESSAGE = _("no live message saved") + +# Translators: A live region is an area of a web page that is periodically +# updated, e.g. stock ticker. http://www.w3.org/TR/wai-aria/terms#def_liveregion +# Cthulhu has several features to facilitate accessing live regions. This message +# is presented to inform the user that Cthulhu's live region features have been +# turned off. +LIVE_REGIONS_OFF = _("Live region support is off") + +# Translators: Cthulhu has a command that allows the user to move the mouse pointer +# to the current object. This is a brief message which will be presented if for +# some reason Cthulhu cannot identify/find the current location. +LOCATION_NOT_FOUND_BRIEF = C_("location", "Not found") + +# Translators: Cthulhu has a command that allows the user to move the mouse pointer +# to the current object. This is a detailed message which will be presented if +# for some reason Cthulhu cannot identify/find the current location. +LOCATION_NOT_FOUND_FULL = _("Could not find current location.") + +# Translators: This string is used to present the state of a locking key, such +# as Caps Lock. If Caps Lock is "off", then letters typed will appear in +# lowercase; if Caps Lock is "on", they will instead appear in uppercase. This +# string is also applied to Num Lock and potentially will be applied to similar +# keys in the future. +LOCKING_KEY_STATE_OFF = C_("locking key state", "off") + +# Translators: This string is used to present the state of a locking key, such +# as Caps Lock. If Caps Lock is "off", then letters typed will appear in +# lowercase; if Caps Lock is "on", they will instead appear in uppercase. This +# string is also applied to Num Lock and potentially will be applied to similar +# keys in the future. +LOCKING_KEY_STATE_ON = C_("locking key state", "on") + +# Translators: This is to inform the user of the presence of the red squiggly +# line which indicates that a given word is not spelled correctly. +MISSPELLED = _("misspelled") + +# Translators: Cthulhu tries to provide more compelling output of the spell check +# dialog in some applications. The first thing it does is let the user know +# what the misspelled word is. +MISSPELLED_WORD = _("Misspelled word: %s") + +# Translators: Cthulhu tries to provide more compelling output of the spell check +# dialog in some applications. The second thing it does is give the phrase +# containing the misspelled word in the document. This is known as the context. +MISSPELLED_WORD_CONTEXT = _("Context is %s") + +# Translators: Cthulhu has a number of commands that override the default +# behavior within an application. For instance, on a web page, "h" moves +# you to the next heading. What should happen when you press an "h" in +# an entry on a web page depends: If you want to resume reading content, +# "h" should move to the next heading; if you want to enter text, "h" +# should not move you to the next heading. Similarly, if you are +# at the bottom of an entry and press Down arrow, should you leave the +# entry? Again, it depends on if you want to resume reading content or +# if you are editing the text in the entry. Because Cthulhu doesn't know +# what you want to do, it has two modes: In browse mode, Cthulhu treats +# key presses as commands to read the content; in focus mode, Cthulhu treats +# key presses as something that should be handled by the focused widget. +# This string is the message presented when Cthulhu switches to browse mode. +MODE_BROWSE = _("Browse mode") + +# Translators: Cthulhu has a number of commands that override the default +# behavior within an application. For instance, on a web page, "h" moves +# you to the next heading. What should happen when you press an "h" in +# an entry on a web page depends: If you want to resume reading content, +# "h" should move to the next heading; if you want to enter text, "h" +# should not move you to the next heading. Similarly, if you are +# at the bottom of an entry and press Down arrow, should you leave the +# entry? Again, it depends on if you want to resume reading content or +# if you are editing the text in the entry. Because Cthulhu doesn't know +# what you want to do, it has two modes: In browse mode, Cthulhu treats +# key presses as commands to read the content; in focus mode, Cthulhu treats +# key presses as something that should be handled by the focused widget. +# This string is the message presented when Cthulhu switches to focus mode. +MODE_FOCUS = _("Focus mode") + +# Translators: Cthulhu has a number of commands that override the default +# behavior within an application. For instance, on a web page, "h" moves +# you to the next heading. What should happen when you press an "h" in +# an entry on a web page depends: If you want to resume reading content, +# "h" should move to the next heading; if you want to enter text, "h" +# should not move you to the next heading. Similarly, if you are +# at the bottom of an entry and press Down arrow, should you leave the +# entry? Again, it depends on if you want to resume reading content or +# if you are editing the text in the entry. Because Cthulhu doesn't know +# what you want to do, it has two modes: In browse mode, Cthulhu treats +# key presses as commands to read the content; in focus mode, Cthulhu treats +# key presses as something that should be handled by the focused widget. +# This string is a tutorial message presented to the user who has just +# navigated to a widget in browse mode to inform them of the keystroke +# they must press to enable focus mode for the purposes of interacting +# with the widget. The substituted string is a human-consumable keybinding +# such as "Alt+Shift+A." +MODE_FOCUS_TUTORIAL = _("To enable focus mode press %s.") + +# Translators: (Please see the previous, detailed translator notes about +# Focus mode and Browse mode.) In order to minimize the amount of work Cthulhu +# users need to do to switch between focus mode and browse mode, Cthulhu attempts +# to automatically switch to the mode which is appropriate to the current +# web element. Sometimes, however, this automatic mode switching is not what +# the user wants. A good example being web apps which have their own keyboard +# navigation and use interaction model. As a result, Cthulhu has a command which +# enables setting a "sticky" focus mode which disables all automatic toggling. +# This string is the message presented when Cthulhu switches to sticky focus mode. +MODE_FOCUS_IS_STICKY = _("Focus mode is sticky.") + +# Translators: (Please see the previous, detailed translator notes about +# Focus mode and Browse mode.) In order to minimize the amount of work Cthulhu +# users need to do to switch between focus mode and browse mode, Cthulhu attempts +# to automatically switch to the mode which is appropriate to the current +# web element. Sometimes, however, this automatic mode switching is not what +# the user wants. A good example being web apps which have their own keyboard +# navigation and use interaction model. As a result, Cthulhu has a command which +# enables setting a "sticky" browse mode which disables all automatic toggling. +# This string is the message presented when Cthulhu switches to sticky browse mode. +MODE_BROWSE_IS_STICKY = _("Browse mode is sticky.") + +# Translators: When presenting the content of a line on a web page, Cthulhu by +# default presents the full line, including any links or form fields on that +# line, in order to reflect the on-screen layout as seen by sighted users. +# Not all users like this presentation, however, and prefer to have objects +# treated as if they were on individual lines, such as is done by Windows +# screen readers, so that unrelated objects (e.g. links in a navbar) are not +# all jumbled together. As a result, this is now configurable. If layout mode +# is enabled, Cthulhu will present the full line as it appears on the screen; if +# it is disabled, Cthulhu will treat each object as if it were on a separate line, +# both for presentation and navigation. This string is presented when the user +# switches to layout mode via an Cthulhu command. +MODE_LAYOUT = _("Layout mode.") + +# Translators: When presenting the content of a line on a web page, Cthulhu by +# default presents the full line, including any links or form fields on that +# line, in order to reflect the on-screen layout as seen by sighted users. +# Not all users like this presentation, however, and prefer to have objects +# treated as if they were on individual lines, such as is done by Windows +# screen readers, so that unrelated objects (e.g. links in a navbar) are not +# all jumbled together. As a result, this is now configurable. If layout mode +# is enabled, Cthulhu will present the full line as it appears on the screen; if +# it is disabled, Cthulhu will treat each object as if it were on a separate line, +# both for presentation and navigation. This string is presented when the user +# toggles layout mode off via an Cthulhu command and switches to the aforementioned +# object-based presentation. +MODE_OBJECT = _("Object mode.") + +# Translators: This message is presented to the user when the command to move +# the mouse pointer to a particular object is believed to have succeeded. +MOUSE_MOVED_SUCCESS = _("Pointer moved to object.") + +# Translators: Hovering the mouse over certain objects on a web page causes a +# new object to appear such as a pop-up menu. Cthulhu has a command will move the +# user to the object which just appeared as a result of the user hovering the +# mouse. If this command fails, Cthulhu will present this message. +MOUSE_OVER_NOT_FOUND = _("Mouse over object not found.") + +# Translators: Cthulhu has a feature to speak the item under the pointer. This feature, +# known as mouse review, can be enabled and disabled via command. The following is +# the message which Cthulhu will present when mouse review is toggled off via command. +MOUSE_REVIEW_DISABLED = _("Mouse review disabled.") + +# Translators: Cthulhu has a feature to speak the item under the pointer. This feature, +# known as mouse review, can be enabled and disabled via command. The following is +# the message which Cthulhu will present when mouse review is toggled on via command. +MOUSE_REVIEW_ENABLED = _("Mouse review enabled.") + +# Translators: Cthulhu has a command that presents a list of structural navigation +# objects in a dialog box so that users can navigate more quickly than they +# could with native keyboard navigation. This is a message that will be +# presented to the user when an error (such as the operation timing out) kept us +# from getting these objects. +NAVIGATION_DIALOG_ERROR = _("Error: Could not create list of objects.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This message is spoken when the current node in the hierarchy +# has no children. +NAVIGATOR_NO_CHILDREN = _("No children.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This message is spoken when the current node in the hierarchy +# has no next sibling. +NAVIGATOR_NO_NEXT = _("No next.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This message is spoken when the current node in the hierarchy +# has no parent. +NAVIGATOR_NO_PARENT = _("No parent.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This message is spoken when the current node in the hierarchy +# has no previous sibling. +NAVIGATOR_NO_PREVIOUS = _("No previous.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This hierarchy can be simplified to aid with navigation. This +# message is spoken when the simplified view is enabled. +NAVIGATOR_SIMPLIFIED_ENABLED = _("Simplified navigation enabled.") + +# Translators: the object navigator allows users to explore UI objects presented +# as a hierarchy. This hierarchy can be simplified to aid with navigation. This +# message is spoken when the simplified view is disabled. +NAVIGATOR_SIMPLIFIED_DISABLED = _("Simplified navigation disabled.") + +# Translators: This message describes a list item in a document. Nesting level +# is how "deep" the item is (e.g., a level of 2 represents a list item inside a +# list that's inside another list). +NESTING_LEVEL = _("Nesting level %d") + +# Translators: Cthulhu has a command that moves the mouse pointer to the current +# location on a web page. If moving the mouse pointer caused an item to appear +# such as a pop-up menu, we want to present that fact. +NEW_ITEM_ADDED = _("New item has been added") + +# Translators: Cthulhu has a command which presents a menu with accessible actions +# that can be performed on the current object. This is the message that Cthulhu +# presents when the object has no actions. The string substitution will be the +# name of the object if it has a name (e.g. "OK" or "Close") or it's accessible, +# localized rolename if it does not. +NO_ACTIONS_FOUND_ON = _("No actions found on: %s") + +# Translators: This is intended to be a short phrase to present the fact that no +# no accessible component has keyboard focus. +NO_FOCUS = _("No focus") + +# Translators: This message presents the fact that no accessible application has +# has keyboard focus. +NO_FOCUSED_APPLICATION = _("No application has focus.") + +# Translators: This is for navigating document content by moving from blockquote +# to blockquote. This is a detailed message which will be presented to the user +# if no more blockquotes can be found. +NO_MORE_BLOCKQUOTES = _("No more blockquotes.") + +# Translators: This is for navigating document content by moving from button +# to button. This is a detailed message which will be presented to the user +# if no more buttons can be found. +NO_MORE_BUTTONS = _("No more buttons.") + +# Translators: This is for navigating document content by moving from check +# box to check box. This is a detailed message which will be presented to the +# user if no more check boxes can be found. +NO_MORE_CHECK_BOXES = _("No more check boxes.") + +# Translators: This is for navigating document content by moving from 'large +# object' to 'large object'. A 'large object' is a logical chunk of text, +# such as a paragraph, a list, a table, etc. This is a detailed message which +# will be presented to the user if no more check boxes can be found. +NO_MORE_CHUNKS = _("No more large objects.") + +# Translators: This is for navigating document content by moving amongst web +# elements which have an "onClick" action. This is a detailed message which +# will be presented to the user if no more clickable elements can be found. +NO_MORE_CLICKABLES = _("No more clickables.") + +# Translators: This is for navigating document content by moving from combo +# box to combo box. This is a detailed message which will be presented to the +# user if no more combo boxes can be found. +NO_MORE_COMBO_BOXES = _("No more combo boxes.") + +# Translators: This is for navigating document content by moving from entry +# to entry. This is a detailed message which will be presented to the user +# if no more entries can be found. +NO_MORE_ENTRIES = _("No more entries.") + +# Translators: This is for navigating document content by moving from form +# field to form field. This is a detailed message which will be presented to +# the user if no more form fields can be found. +NO_MORE_FORM_FIELDS = _("No more form fields.") + +# Translators: This is for navigating document content by moving from heading +# to heading. This is a detailed message which will be presented to the user +# if no more headings can be found. +NO_MORE_HEADINGS = _("No more headings.") + +# Translators: This is for navigating document content by moving from heading +# to heading at a particular level (i.e. only

or only

, etc.). This +# is a detailed message which will be presented to the user if no more headings +# at the desired level can be found. +NO_MORE_HEADINGS_AT_LEVEL = _("No more headings at level %d.") + +# Translators: This is for navigating document content by moving from iframe +# to iframe. This is a detailed message which will be presented to the user +# if no more iframes can be found. +NO_MORE_IFRAMES = _("No more internal frames.") + +# Translators: This is for navigating document content by moving from image +# to image. This is a detailed message which will be presented to the user +# if no more images can be found. +NO_MORE_IMAGES = _("No more images.") + +# Translators: this is for navigating to the previous ARIA role landmark. +# ARIA role landmarks are the W3C defined HTML tag attribute 'role' used to +# identify important part of webpage like banners, main context, search etc. +# This is an indication that one was not found. +NO_LANDMARK_FOUND = _("No landmark found.") + +# Translators: This is for navigating document content by moving from link to +# link (regardless of visited state). This is a detailed message which will be +# presented to the user if no more links can be found. +NO_MORE_LINKS = _("No more links.") + +# Translators: This is for navigating document content by moving from bulleted/ +# numbered list to bulleted/numbered list. This is a detailed message which will +# be presented to the user if no more lists can be found. +NO_MORE_LISTS = _("No more lists.") + +# Translators: This is for navigating document content by moving from bulleted/ +# numbered list item to bulleted/numbered list item. This is a detailed message +# which will be presented to the user if no more list items can be found. +NO_MORE_LIST_ITEMS = _("No more list items.") + +# Translators: This is for navigating document content by moving from live +# region to live region. A live region is an area of a web page that is +# periodically updated, e.g. stock ticker. This is a detailed message which +# will be presented to the user if no more live regions can be found. For +# more info, see http://www.w3.org/TR/wai-aria/terms#def_liveregion +NO_MORE_LIVE_REGIONS = _("No more live regions.") + +# Translators: This is for navigating document content by moving from paragraph +# to paragraph. This is a detailed message which will be presented to the user +# if no more paragraphs can be found. +NO_MORE_PARAGRAPHS = _("No more paragraphs.") + +# Translators: This is for navigating document content by moving from radio +# button to radio button. This is a detailed message which will be presented to +# the user if no more radio buttons can be found. +NO_MORE_RADIO_BUTTONS = _("No more radio buttons.") + +# Translators: This is for navigating document content by moving from separator +# to separator (e.g.
tags). This is a detailed message which will be +# presented to the user if no more separators can be found. +NO_MORE_SEPARATORS = _("No more separators.") + +# Translators: This is for navigating document content by moving from table to +# to table. This is a detailed message which will be presented to the user if +# no more tables can be found. +NO_MORE_TABLES = _("No more tables.") + +# Translators: This is for navigating document content by moving from unvisited +# link to unvisited link. This is a detailed message which will be presented to +# the user if no more unvisited links can be found. +NO_MORE_UNVISITED_LINKS = _("No more unvisited links.") + +# Translators: This is for navigating document content by moving from visited +# link to visited link. This is a detailed message which will be presented to +# the user if no more visited links can be found. +NO_MORE_VISITED_LINKS = _("No more visited links.") + +# Translators: Cthulhu has a dedicated command to speak the currently-selected +# text. This message is what Cthulhu will present if the user performs this +# command when no text is selected. +NO_SELECTED_TEXT = _("No selected text.") + +# Translators: Cthulhu has a dedicated command to speak detailed information +# about the currently-focused link. This message is what Cthulhu will present +# if the user performs this command when not on a link. +NOT_ON_A_LINK = _("Not on a link.") + +# Translators: This message alerts the user to the fact that what will be +# presented next came from a notification. +NOTIFICATION = _("Notification") + +# Translators: This is a brief message presented to the user when the bottom of +# the list of notifications is reached. +NOTIFICATION_LIST_BOTTOM = C_("notification", "Bottom") + +# Translators: This is a brief message presented to the user when the top of the +# list of notifications is reached. +NOTIFICATION_LIST_TOP = C_("notification", "Top") + +# Translators: This message is presented to the user when the notifications list +# is empty. +NOTIFICATION_NO_MESSAGES = _("No notification messages") + +# Translators: Cthulhu has a setting through which users can control how a number is +# spoken. The options are digits ("1 2 3") and words ("one hundred and twenty +# three"). There is an associated Cthulhu command for quickly toggling between the +# two options. This string to be translated is the brief message spoken when the +# user has enabled speaking numbers as digits. +NUMBER_STYLE_DIGITS_BRIEF = C_("number style", "digits") + +# Translators: Cthulhu has a setting through which users can control how a number is +# spoken. The options are digits ("1 2 3") and words ("one hundred and twenty +# three"). There is an associated Cthulhu command for quickly toggling between the +# two options. This string to be translated is the verbose message spoken when +# the user has enabled speaking numbers as digits. +NUMBER_STYLE_DIGITS_FULL = _("Speak numbers as digits.") + +# Translators: Cthulhu has a setting through which users can control how a number is +# spoken. The options are digits ("1 2 3") and words ("one hundred and twenty +# three"). There is an associated Cthulhu command for quickly toggling between the +# two options. This string to be translated is the brief message spoken when the +# user has enabled speaking numbers as words. +NUMBER_STYLE_WORDS_BRIEF = C_("number style", "words") + +# Translators: Cthulhu has a setting through which users can control how a number is +# spoken. The options are digits ("1 2 3") and words ("one hundred and twenty +# three"). There is an associated Cthulhu command for quickly toggling between the +# two options. This string to be translated is the verbose message spoken when +# the user has enabled speaking numbers as words. +NUMBER_STYLE_WORDS_FULL = _("Speak numbers as words.") + +# Translators: This brief message is presented to indicate the state of widgets +# (checkboxes, push buttons, toggle buttons) on a toolbar which are associated +# with text formatting (bold, italics, underlining, justification, etc.). +OFF = _("off") + +# Translators: This brief message is presented to indicate the state of widgets +# (checkboxes, push buttons, toggle buttons) on a toolbar which are associated +# with text formatting (bold, italics, underlining, justification, etc.). +ON = _("on") + +# Translators: This message is presented to the user when a web page or similar +# item has started loading. +PAGE_LOADING_START = _("Loading. Please wait.") + +# Translators: This message is presented to the user when a web page or similar +# item has finished loading. +PAGE_LOADING_END = _("Finished loading.") + +# Translators: This message is presented to the user when a web page or similar +# item has finished loading. The string substitution is for the name of the +# object which has just finished loading (most likely the page's title). +PAGE_LOADING_END_NAMED = _("Finished loading %s.") + +# Translators: When the user loads a new web page, they can optionally have Cthulhu +# automatically summarize details about the page, such as the number of elements +# (landmarks, forms, links, tables, etc.). The following string precedes the +# presentation of the summary. The string substitution is a list of items, such +# as "10 headings, 1 form, 52 links". +PAGE_SUMMARY_PREFIX = _("Page has %s.") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the end of the page by pressing Shift+Page_Down. +PAGE_SELECTED_DOWN = _("page selected from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the start of the page by pressing Shift+Page_Up. +PAGE_SELECTED_UP = _("page selected to cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects a previously +# selected page by pressing Shift+Page_Down. +PAGE_UNSELECTED_DOWN = _("page unselected from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects a previously +# selected page by pressing Shift+Page_Up. +PAGE_UNSELECTED_UP = _("page unselected to cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the end of the paragraph by pressing Ctrl+Shift+Down. +PARAGRAPH_SELECTED_DOWN = _("paragraph selected down from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user selects from the +# current location to the start of the paragraph by pressing Ctrl+Shift+UP. +PARAGRAPH_SELECTED_UP = _("paragraph selected up from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects previously +# selected text from the current location to the end of the paragraph by +# pressing Ctrl+Shift+Down. +PARAGRAPH_UNSELECTED_DOWN = _("paragraph unselected down from cursor position") + +# Translators: when the user selects (highlights) or unselects text in a +# document, Cthulhu will speak information about what they have selected or +# unselected. This message is presented when the user unselects previously +# selected text from the current location to the start of the paragraph by +# pressing Ctrl+Shift+UP. +PARAGRAPH_UNSELECTED_UP = _("paragraph unselected up from cursor position") + +# Translators: This message appears in a warning dialog when the user performs +# the command to get into Cthulhu's preferences dialog when the preferences dialog +# is already open. +PREFERENCES_WARNING_DIALOG = \ + _('You already have an instance of an Cthulhu preferences dialog ' \ + 'open.\nPlease close it before opening a new one.') + +# Translators: This message is an indication of the position of the focused +# slide and the total number of slides in the presentation. +PRESENTATION_SLIDE_POSITION = _("slide %(position)d of %(count)d") + +# Translators: This is a detailed message which will be presented as the user +# cycles amongst his/her saved profiles. A "profile" is a collection of settings +# which apply to a given task, such as a "Spanish" profile which would use +# Spanish text-to-speech and Spanish braille and selected when reading Spanish +# content. The string representing the profile name is created by the user. +PROFILE_CHANGED = _("Profile set to %s.") + +# Translators: This is an error message presented when the user attempts to +# cycle among his/her saved profiles, but no profiles can be found. A profile +# is a collection of settings which apply to a given task, such as a "Spanish" +# profile which would use Spanish text-to-speech and Spanish braille and +# selected when reading Spanish content. +PROFILE_NOT_FOUND = _("No profiles found.") + +# Translators: this is an index value so that we can present value changes +# regarding a specific progress bar in environments where there are multiple +# progress bars (e.g. in the Firefox downloads dialog). +PROGRESS_BAR_NUMBER = _("Progress bar %d.") + +# Translators: This brief message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_ALL_BRIEF = C_("spoken punctuation", "All") + +# Translators: This detailed message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_ALL_FULL = _("Punctuation level set to all.") + +# Translators: This brief message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_MOST_BRIEF = C_("spoken punctuation", "Most") + +# Translators: This detailed message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_MOST_FULL = _("Punctuation level set to most.") + +# Translators: This brief message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_NONE_BRIEF = C_("spoken punctuation", "None") + +# Translators: This detailed message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_NONE_FULL = _("Punctuation level set to none.") + +# Translators: This brief message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_SOME_BRIEF = C_("spoken punctuation", "Some") + +# Translators: This detailed message will be presented as the user cycles +# through the different levels of spoken punctuation. The options are: +# All punctuation marks will be spoken, None will be spoken, Most will be +# spoken, or Some will be spoken. +PUNCTUATION_SOME_FULL = _("Punctuation level set to some.") + +# Translators: This message is presented to indicate that a search has begun +# or is still taking place. +SEARCHING = _("Searching.") + +# Translators: This message is presented to indicate a search executed by the +# user has been completed. +SEARCH_COMPLETE = _("Search complete.") + +# Translators: This message is presented to the user when Cthulhu's preferences +# have been reloaded. +SETTINGS_RELOADED = _("Cthulhu settings reloaded.") + +# Translators: Cthulhu has a dedicated command to speak the currently-selected +# text. This message is spoken by Cthulhu before speaking the text which is +# selected. The string substitution is for the selected text. +SELECTED_TEXT_IS = _("Selected text is: %s") + +# Translators: Cthulhu normal speaks the text which was just deleted from a +# document via command. Depending on the circumstances, that might be a +# large string. Therefore, if the text which has just been deleted from a +# document matches the previously-selected contents, Cthulhu will indicate that +# fact instead of presenting the full string which was just deleted. +SELECTION_DELETED = _("Selection deleted.") + +# Translators: Cthulhu normal speaks the text which was just inserted into a +# document via command. Depending on the circumstances, that might be a +# large string. Therefore, if the text which has just been inserted into a +# document is also already selected, it is likely that the insertion is +# due to having been restored (e.g. the user selected text, deleted it, +# and then pressed Ctrl+Z to undo that deletion). In this instance, Cthulhu +# will indicate the restoration rather than presenting the full string +# which was just inserted. +SELECTION_RESTORED = _("Selection restored.") + +# Translators: This message is presented to the user when text had been +# selected in a document and no longer is, e.g. as the result of navigating +# without holding down the shift key. +SELECTION_REMOVED = _("Text unselected.") + +# Translators: Cthulhu has a command which presents the size and position of the +# current object in pixels. This string refers to the brief/non-verbose output +# presented in response to the command. The string substitutions are all for +# quantities (in pixels). +SIZE_AND_POSITION_BRIEF = _("Size: %d, %d. Location: %d, %d.") + +# Translators: Cthulhu has a command which presents the size and position of the +# current object in pixels. This string refers to the full/verbose output +# presented in response to the command. The string substitutions are all for +# quantities (in pixels). +SIZE_AND_POSITION_FULL = _("Width: %d. Height: %d. %d from left. %d from top.") + +# Translators: This message is presented to the user when speech synthesis +# has been temporarily turned off. +SPEECH_DISABLED = _("Speech disabled.") + +# Translators: This message is presented to the user when speech synthesis +# has been turned back on. +SPEECH_ENABLED = _("Speech enabled.") + +# Translators: This string announces speech rate change. +SPEECH_FASTER = _("faster.") + +# Translators: This string announces speech rate change. +SPEECH_SLOWER = _("slower.") + +# Translators: This string announces speech pitch change. +SPEECH_HIGHER = _("higher.") + +# Translators: This string announces speech pitch change. +SPEECH_LOWER = _("lower.") + +# Translators: This string announces speech volume change. +SPEECH_LOUDER = _("louder.") + +# Translators: This string announces speech volume change. +SPEECH_SOFTER = _("softer.") + +# Translators: Cthulhu's verbosity levels control how much (or how little) +# Cthulhu will speak when presenting objects as the user navigates within +# applications and reads content. The two levels are "brief" and "verbose". +# The following string is a message spoken to the user upon toggling +# this setting via command. +SPEECH_VERBOSITY_BRIEF = C_("Speech", "Verbosity level: brief") + +# Translators: Cthulhu's verbosity levels control how much (or how little) +# Cthulhu will speak when presenting objects as the user navigates within +# applications and reads content. The two levels are "brief" and "verbose". +# The following string is a message spoken to the user upon toggling +# this setting via command. +SPEECH_VERBOSITY_VERBOSE = C_("Speech", "Verbosity level: verbose") + +# Translators: We replace the ellipses (both manual and UTF-8) with a spoken +# string. The extra space you see at the beginning is because we need the +# speech synthesis engine to speak the new string well. For example, "Open..." +# turns into "Open dot dot dot". +SPOKEN_ELLIPSIS = _(" dot dot dot") + +# Translators: This message is presented to the user when Cthulhu is launched. +START_CTHULHU = _("Cthulhu welcomes you.") + +# Translators: This message is presented to the user when Cthulhu is quit. +STOP_CTHULHU = _("Cthulhu lurks beneath the waves.") + +# Sleep Mode +# Translators: This message is presented to the user when Cthulhu enters or leaves sleep mode. +SLEEP_MODE_ENABLED_FOR = _("Sleep mode enabled for %s") +SLEEP_MODE_DISABLED_FOR = _("Sleep mode disabled for %s") + +# Translators: This message means speech synthesis is not installed or working. +SPEECH_UNAVAILABLE = _("Speech is unavailable.") + +# Translators: Cthulhu has a command to present the contents of the status bar. +# This is a brief message which will be presented if Cthulhu cannot find the +# status bar (e.g. because there isn't one). +STATUS_BAR_NOT_FOUND_BRIEF = C_("status bar", "Not found") + +# Translators: Cthulhu has a command to present the contents of the status bar. +# This is a detailed message which will be presented if Cthulhu cannot find the +# status bar (e.g. because there isn't one). +STATUS_BAR_NOT_FOUND_FULL = _("Status bar not found") + +# Translators: the Cthulhu "Find" dialog allows a user to search for text in a +# window and then move focus to that text. For example, they may want to find +# the "OK" button. This message lets them know a string they were searching +# for was not found. +STRING_NOT_FOUND = _("string not found") + +# Translators: The structural navigation keys are designed to move the caret +# around document content by object type. H moves you to the next heading, +# Shift H to the previous heading, T to the next table, and so on. Some users +# prefer to turn this off to use Firefox's search when typing feature. This +# message is presented when the user toggles the structural navigation feature +# of Cthulhu. It should be a brief informative message. +STRUCTURAL_NAVIGATION_KEYS_OFF = _("Structural navigation keys off.") + +# Translators: The structural navigation keys are designed to move the caret +# around document content by object type. H moves you to the next heading, +# Shift H to the previous heading, T to the next table, and so on. Some users +# prefer to turn this off to use Firefox's search when typing feature. This +# message is presented when the user toggles the structural navigation feature +# of Cthulhu. It should be a brief informative message. +STRUCTURAL_NAVIGATION_KEYS_ON = _("Structural navigation keys on.") + +# Translators: Cthulhu has a command that allows the user to move to the next +# structural navigation object. In Cthulhu, "structural navigation" refers to +# quickly moving through a document by jumping amongst objects of a given +# type, such as from link to link, or from heading to heading, or from form +# field to form field. This is a brief message which will be presented to the +# user if the desired structural navigation object could not be found. +STRUCTURAL_NAVIGATION_NOT_FOUND = C_("structural navigation", "Not found") + +# Translators: This message describes the (row, col) position of a table cell. +TABLE_CELL_COORDINATES = _("Row %(row)d, column %(column)d.") + +# Translators: This message is presented to indicate the user is in the last +# cell of a table in a document. +TABLE_END = _("End of table") + +# Translators: When users are navigating a table, they sometimes want the entire +# row of a table read; other times they want just the current cell presented. +# This string is a message presented to the user when this setting is toggled. +TABLE_MODE_CELL = _("Speak cell") + +# Translators: When users are navigating a table, they sometimes want the entire +# row of a table read; other times they want just the current cell presented. +# This string is a message presented to the user when this setting is toggled. +TABLE_MODE_ROW = _("Speak row") + +# Translators: a uniform table is one in which each table cell occupies one row +# and one column (i.e. a perfect grid). In contrast, a non-uniform table is one +# in which at least one table cell occupies more than one row and/or column. +TABLE_NON_UNIFORM = _("Non-uniform") + +# Translators: This is for navigating document content by moving from table cell +# to table cell. If the user gives a table navigation command but is not in a +# table, presents this message. +TABLE_NOT_IN_A = _("Not in a table.") + +# Translators: This is a message presented to users when the columns in a table +# have been reordered. +TABLE_REORDERED_COLUMNS = _("Columns reordered") + +# Translators: This is a message presented to users when the rows in a table +# have been reordered. +TABLE_REORDERED_ROWS = _("Rows reordered") + +# Translators: this is in reference to a column in a table. The substitution +# is the index (e.g. the first column is "column 1"). +TABLE_COLUMN = _("column %d") + +# Translators: this is in reference to a column in a table. If the user is in +# the first column of a table with five columns, the position is "column 1 of 5" +TABLE_COLUMN_DETAILED = _("column %(index)d of %(total)d") + +# Translators: This is for navigating document content by moving from table cell +# to table cell. This is the message presented when the user attempts to move to +# the cell below the current cell and is already in the last row. +TABLE_COLUMN_BOTTOM = _("Bottom of column.") + +# Translators: This is for navigating document content by moving from table cell +# to table cell. This is the message presented when the user attempts to move to +# the cell above the current cell and is already in the first row. +TABLE_COLUMN_TOP = _("Top of column.") + +# Translators: this message is spoken to announce that a table column just became +# selected (e.g as a result of navigation via Shift + Arrows). The string substitution +# is the column label (e.g. "B"). +TABLE_COLUMN_SELECTED = _("Column %s selected") + +# Translators: this message is spoken to announce that multiple table columns just +# became selected (e.g as a result of navigation via Shift + Arrows). The first +# string substitution is the label of the first column in the range. The second string +# substitution is the label in the last column in the range. An example message for +# Calc would be "Columns B through F selected". +TABLE_COLUMN_RANGE_SELECTED = _("Columns %s through %s selected") + +# Translators: this message is spoken to announce that multiple table columns just +# became unselected (e.g as a result of navigation via Shift + Arrows). The first +# string substitution is the label of the first column in the range. The second string +# substitution is the label in the last column in the range. An example message for +# Calc would be "Columns B through F unselected". +TABLE_COLUMN_RANGE_UNSELECTED = _("Columns %s through %s unselected") + +# Translators: this message is spoken to announce that a table column just became +# unselected (e.g as a result of navigation via Shift + Arrows). The string substitution +# is the column label (e.g. "B"). +TABLE_COLUMN_UNSELECTED = _("Column %s unselected") + +# Translators: this is in reference to a row in a table. The substitution is +# the index (e.g. the first row is "row 1"). +TABLE_ROW = _("row %d") + +# Translators: this is in reference to a row in a table. If the user is in the +# the first row of a table with five rows, the position is "row 1 of 5" +TABLE_ROW_DETAILED = _("row %(index)d of %(total)d") + +# Translators: This is for navigating document content by moving from table cell +# to table cell. This is the message presented when the user attempts to move to +# the left of the current cell and is already in the first column. +TABLE_ROW_BEGINNING = _("Beginning of row.") + +# Translators: This is for navigating document content by moving from table cell +# to table cell. This is the message presented when the user attempts to move to +# the right of the current cell and is already in the last column. +TABLE_ROW_END = _("End of row.") + +# Translators: This message is presented to the user to confirm that he/she just +# deleted a table row. +TABLE_ROW_DELETED = _("Row deleted.") + +# Translators: This message is presented to the user to confirm that he/she just +# deleted the last row of a table. +TABLE_ROW_DELETED_FROM_END = _("Last row deleted.") + +# Translators: This message is presented to the user to confirm that he/she just +# inserted a table row. +TABLE_ROW_INSERTED = _("Row inserted.") + +# Translators: This message is presented to the user to confirm that he/she just +# inserted a table row at the end of the table. This typically happens when the +# user presses Tab from within the last cell of the table. +TABLE_ROW_INSERTED_AT_END = _("Row inserted at the end of the table.") + +# Translators: this message is spoken to announce that a table row just became selected +# (e.g as a result of navigation via Shift + Arrows). The string substitution is the row +# label (e.g. "2"). +TABLE_ROW_SELECTED = _("Row %s selected") + +# Translators: this message is spoken to announce that multiple table rows just +# became selected (e.g as a result of navigation via Shift + Arrows). The first +# string substitution is the label of the first row in the range. The second string +# substitution is the label of the last row in the range. An example message for +# Calc would be "Rows 2 through 10 selected". +TABLE_ROW_RANGE_SELECTED = _("Rows %s through %s selected") + +# Translators: this message is spoken to announce that multiple table rows just +# became unselected (e.g as a result of navigation via Shift + Arrows). The first +# string substitution is the label of the first row in the range. The second string +# substitution is the label of the last row in the range. An example message for +# Calc would be "Rows 2 through 10 unselected". +TABLE_ROW_RANGE_UNSELECTED = _("Rows %s through %s unselected") + +# Translators: this message is spoken to announce that a table row just became +# unselected (e.g as a result of navigation via Shift + Arrows). The string +# substitution is the row label (e.g. "2"). +TABLE_ROW_UNSELECTED = _("Row %s unselected") + +# Translators: when the user selects (highlights) text in a document, Cthulhu lets +# them know. +TEXT_SELECTED = C_("text", "selected") + +# Translators: when the user unselects (un-highlights) text in a document, Cthulhu +# lets them know. +TEXT_UNSELECTED = C_("text", "unselected") + +TIME_FORMAT_LOCALE = "%X" +TIME_FORMAT_24_HMS = "%H:%M:%S" +TIME_FORMAT_24_HM = "%H:%M" +TIME_FORMAT_12_HM = "%I:%M %p" +TIME_FORMAT_12_HMS = "%I:%M:%S %p" + +# Translators: Cthulhu has a feature to speak the time when the user presses a +# shortcut key. This is one of the alternative formats that the user may wish +# it to be presented with. +TIME_FORMAT_24_HMS_WITH_WORDS = _("%H hours, %M minutes and %S seconds") + +# Translators: Cthulhu has a feature to speak the time when the user presses a +# shortcut key. This is one of the alternative formats that the user may wish +# it to be presented with. +TIME_FORMAT_24_HM_WITH_WORDS = _("%H hours and %M minutes") + +# Translators: this is information about a unicode character reported to the +# user. The value is the unicode number value of this character in hex. +UNICODE = _("Unicode %s") + +# Translators: This string is presented when an application's undo command is +# used in a document resulting in a change to that document's contents. +UNDO = C_("command", "undo") + +# Translators: This string is presented when an application's redo command is +# used in a document resulting in a change to that document's contents. +REDO = C_("command", "redo") + +# Translators: This message presents the Cthulhu version number. +VERSION = _("Cthulhu version %s.") % version + +# Translators: This is presented when the user has navigated to a line with only +# whitespace characters (space, tab, etc.) on it. +WHITE_SPACE = _("white space") + +# Translators: when the user is attempting to locate a particular object and the +# top of a page or list is reached without that object being found, we "wrap" to +# the bottom and continue looking upwards. We need to inform the user when this +# is taking place. +WRAPPING_TO_BOTTOM = _("Wrapping to bottom.") + +# Translators: when the user is attempting to locate a particular object and the +# bottom of a page or list is reached without that object being found, we "wrap" +# to the top and continue looking downwards. We need to inform the user when +# this is taking place. +WRAPPING_TO_TOP = _("Wrapping to top.") + +# Translators, normally layered panes and tables have items in them. Thus it is +# noteworthy when this is not the case. This message is presented to the user to +# indicate the current layered pane or table contains zero items. +ZERO_ITEMS = _("0 items") + +def cellSpan(rowspan, colspan): + spanString = "" + if (colspan > 1) and (rowspan > 1): + # Translators: The cell here refers to a cell within a table within a + # document. We need to announce when the cell occupies or "spans" more + # than a single row and/or column. + spanString = ngettext("Cell spans %d row", + "Cell spans %d rows", + rowspan) % rowspan + + # Translators: this represents the number of columns in a table. + spanString += ngettext(" %d column", + " %d columns", + colspan) % colspan + elif (colspan > 1): + # Translators: The cell here refers to a cell within a table within a + # document. We need to announce when the cell occupies or "spans" more + # than a single row and/or column. + spanString = ngettext("Cell spans %d column", + "Cell spans %d columns", + colspan) % colspan + elif (rowspan > 1): + # Translators: The cell here refers to a cell within a table within a + # document. We need to announce when the cell occupies or "spans" more + # than a single row and/or column. + spanString = ngettext("Cell spans %d row", + "Cell spans %d rows", + rowspan) % rowspan + + return spanString + +def charactersTooLong(count): + # Translators: People can enter a string of text that is too wide to be + # fully displayed in a spreadsheet cell. This message will be spoken if + # such a cell is encountered. + return ngettext("%d character too long", + "%d characters too long", + count) % count + +def dialogCountBraille(count): + # Translators: This message informs the user how many unfocused alert and + # dialog windows a newly (re)focused application has. It is added at the + # end of a braille message containing the app which just claimed focus. + return ngettext("(%d dialog)", "(%d dialogs)", count) % count + +def dialogCountSpeech(count): + # Translators: This message informs the user how many unfocused alert and + # dialog windows a newly (re)focused application has. It is added at the + # end of a spoken message containing the app which just claimed focus. + return ngettext("%d unfocused dialog", "%d unfocused dialogs", count) % count + +def fileSizeBytes(size): + # Translators: This is the size of a file in bytes + return ngettext("%d byte", "%d bytes", size) % size + +def filesFound(count): + # Translators: This message informs the user who many files were found as + # a result of a search. + return ngettext("%d file found", "%d files found", count) % count + +def formCount(count, onlyIfFound=True): + if not count and onlyIfFound: + return "" + + # Translators: This message presents the number of forms in a document. + return ngettext("%d form", "%d forms", count) % count + +def headingCount(count, onlyIfFound=True): + if not count and onlyIfFound: + return "" + + # Translators: This message presents the number of headings in a document. + return ngettext("%d heading", "%d headings", count) % count + +def itemCount(count): + # Translators: This message presents the number of items in a layered pane + # or table. + return ngettext("%d item", "%d items", count) % count + +def landmarkCount(count, onlyIfFound=True): + if not count and onlyIfFound: + return "" + + # Translators: This message presents the number of landmarks in a document. + # ARIA role landmarks are the W3C defined HTML tag attribute 'role' used to + # identify important part of webpage like banners, main context, search etc. + return ngettext("%d landmark", "%d landmarks", count) % count + +def itemsFound(count): + # Translators: Cthulhu has several commands that search for, and present a list + # of, objects based on one or more criteria. This is a message that will be + # presented to the user to indicate how many matching items were found. + return ngettext("%d item found", "%d items found", count) % count + +def leavingNBlockquotes(count): + # Translators: This message is presented when a user is navigating within a + # series of nested blockquotes, such as can be seen in deep email threads, + # and then navigates out of several levels at once. + return ngettext("Leaving %d blockquote.", "Leaving %d blockquotes.", count) % count + +def leavingNLists(count): + # Translators: This message is presented when a user is navigating within a + # series of nested lists and then navigates out of several levels at once. + return ngettext("Leaving %d list.", "Leaving %d lists.", count) % count + +def listItemCount(count): + if count == -1: + # Translators: This message describes a list in web content for which the + # size is unknown. Examples include unlimited scrolling news/article feeds + # on social media sites, and message lists on services such as gmail where + # you're currently viewing messages 1-100 out of some huge, unspecified + # number. Normally Cthulhu announces "list with n items" when the count is + # known. This is the corresponding message for the unknown-count scenario. + return _("List of unknown size") + + # Translators: This message describes a bulleted or numbered list. + return ngettext("List with %d item", "List with %d items", count) % count + +def feedArticleCount(count): + if count == -1: + # Translators: This message describes a news/article feed whose size is + # unknown, such as can be found on social media sites that have unlimited + # scrolling, adding and/or removing items as the user moves up or down. + # Normally Cthulhu announces "feed with n articles" when the count is known. + # This is the corresponding message for the unknown-count scenario. + return _("Feed of unknown size") + + # Translators: This message describes the number of articles (news items, + # social media posts, etc.) in a feed. + return ngettext("Feed with %d article", "Feed with %d articles", count) % count + +def descriptionListTermCount(count): + # Translators: This message describes a description list. + # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl + # Note that the "term" here corresponds to the "dt" element + return ngettext("Description list with %d term", + "Description list with %d terms", count) % count + +def valueCountForTerm(count): + # Translators: This message describes a description list. + # A given term ("dt" element) can have 0 or more values ("dd" elements). + # This message presents the number values a particular term has. + # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl + return ngettext("%d value", "%d values", count) % count + +def mathTableSize(nRows, nColumns): + # Translators: this represents the number of rows in a mathematical table. + # See http://www.w3.org/TR/MathML3/chapter3.html#presm.mtable + rowString = ngettext("math table with %d row", + "math table with %d rows", + nRows) % nRows + # Translators: this represents the number of columns in a mathematical table. + # See http://www.w3.org/TR/MathML3/chapter3.html#presm.mtable + colString = ngettext("%d column", + "%d columns", + nColumns) % nColumns + + return rowString + " " + colString + +def mathNestedTableSize(nRows, nColumns): + # Translators: this represents the number of rows in a mathematical table + # which is nested inside another mathematical table. + # See http://www.w3.org/TR/MathML3/chapter3.html#presm.mtable + rowString = ngettext("nested math table with %d row", + "nested math table with %d rows", + nRows) % nRows + # Translators: this represents the number of rows in a mathematic table + # which is nested inside another mathematical table. + # See http://www.w3.org/TR/MathML3/chapter3.html#presm.mtable + colString = ngettext("%d column", + "%d columns", + nColumns) % nColumns + + return rowString + " " + colString + +def messagesCount(count): + # Translators: This message is presented to inform the user of the number of + # messages in a list. + return ngettext("%d message.\n", "%d messages.\n", count) % count + +def percentage(value): + # Translators: This message is presented to inform the user of the value of + # a slider, progress bar, or other such component. + return ngettext("%d percent.", "%d percent.", value) % value + +def percentRead(value): + # Translators: This message announces the percentage of the document that + # has been read. The value is calculated by knowing the index of the current + # position divided by the total number of objects on the page. + return ngettext ("%d percent of document read", + "%d percent of document read", + value) % value + +def pixelCount(nPixels): + # Translators: this represents a text attribute expressed in pixels, such as + # a margin, indentation, font size, etc. + return ngettext("%d pixel", "%d pixels", nPixels) % nPixels + +def repeatedCharCount(repeatChar, count): + # Translators: Cthulhu will tell you how many characters are repeated on a line + # of text. For example: "22 space characters". The %d is the number and the + # %s is the spoken word for the character. + return ngettext("%(count)d %(repeatChar)s character", + "%(count)d %(repeatChar)s characters", + count) % {"count" : count, "repeatChar": repeatChar} + +def selectedItemsCount(selected, total): + # Translators: This message is presented to indicate the number of selected + # objects (e.g. icons) and the total number of those objects. + return ngettext("%(index)d of %(total)d item selected", + "%(index)d of %(total)d items selected", + total) % {"index" : selected, "total" : total} + +def shortcutsFoundCthulhu(count): + # Translators: This message is presented when the user is in a list of + # shortcuts associated with Cthulhu commands which are not specific to the + # current application. It appears as the title of the dialog containing + # the list. + return ngettext("%d Screen reader default shortcut found.", + "%d Screen reader default shortcuts found.", + count) % count + +def shortcutsFoundApp(count, appName): + # Translators: This message is presented when the user is in a list of + # shortcuts associated with Cthulhu commands specific to the current + # application. It appears as the title of the dialog containing the list. + return ngettext("%(count)d Screen reader shortcut for %(application)s found.", + "%(count)d Screen reader shortcuts for %(application)s found.", + count) % {"count" : count, "application" : appName} + +def spacesCount(count): + # Translators: This message is presented to inform the user of the number of + # space characters in a string. + return ngettext("%d space", "%d spaces", count) % count + +def tabsCount(count): + # Translators: This message is presented to inform the user of the number of + # tab characters in a string. + return ngettext("%d tab", "%d tabs", count) % count + +def tableCount(count, onlyIfFound=True): + if not count and onlyIfFound: + return "" + + # Translators: This message presents the number of tables in a document. + return ngettext("%d table", "%d tables", count) % count + +def tableSize(nRows, nColumns): + if nRows == -1: + if nColumns == -1: + # Translators: This message describes a table for which both the + # number of rows and the number of columns are unknown. Normally + # Cthulhu announces the table dimensions (e.g. "table with 100 rows + # 15 columns"). When both counts are unknown, it presents this. + return _("table of unknown size") + + # Translators: This message describes a table for which the number of + # rows is unknown, but the number of columns is known. This might occur + # in a vertically infinitely scrollable table or grid on the web. + return ngettext("table with %d column, row count unknown", + "table with %d columns, row count unknown", + nColumns) % nColumns + + if nColumns == -1: + # Translators: This message describes a table for which the number of + # columns is unknown, but the number of rows is known. This might occur + # in a horizontally infinitely scrollable table or grid on the web. + return ngettext("table with %d row, column count unknown", + "table with %d rows, column count unknown", + nRows) % nRows + + # Translators: this represents the number of rows in a table. + rowString = ngettext("table with %d row", + "table with %d rows", + nRows) % nRows + + # Translators: this represents the number of columns in a table. + colString = ngettext("%d column", + "%d columns", + nColumns) % nColumns + + return rowString + " " + colString + +def secondsAgo(count): + # Translators: This message informs the user how long ago something took + # place in terms of seconds. + return ngettext("%d second ago", "%d seconds ago", count) % count + +def minutesAgo(count): + # Translators: This message informs the user how long ago something took + # place in terms of minutes. + return ngettext("%d minute ago", "%d minutes ago", count) % count + +def hoursAgo(count): + # Translators: This message informs the user how long ago something took + # place in terms of hours. + return ngettext("%d hour ago", "%d hours ago", count) % count + +def daysAgo(count): + # Translators: This message informs the user how long ago something took + # place in terms of days. + return ngettext("%d day ago", "%d days ago", count) % count + +def unvisitedLinkCount(count, onlyIfFound=True): + if not count and onlyIfFound: + return "" + + # Translators: This message presents the number of unvisited links in a + # document. + return ngettext("%d unvisited link", "%d unvisited links", count) % count + +def visitedLinkCount(count, onlyIfFound=True): + if not count and onlyIfFound: + return "" + + # Translators: This message presents the number of visited links in a + # document. + return ngettext("%d visited link", "%d visited links", count) % count diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mouse_review.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mouse_review.py new file mode 100644 index 0000000..de9ed6b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/mouse_review.py @@ -0,0 +1,683 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Mouse review mode.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2008 Eitan Isaacson" \ + "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import math +import time + +from gi.repository import Gdk +try: + gi.require_version("Wnck", "3.0") + from gi.repository import Wnck + _mouseReviewCapable = True +except Exception: + _mouseReviewCapable = False + +from . import cmdnames +from . import debug +from . import keybindings +from . import input_event +from . import messages +from . import cthulhu +from . import cthulhu_state +from . import script_manager +from . import settings_manager +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +_scriptManager = script_manager.getManager() +_settingsManager = settings_manager.getManager() + +class _StringContext: + """The textual information associated with an _ItemContext.""" + + def __init__(self, obj, script=None, string="", start=0, end=0): + """Initialize the _StringContext. + + Arguments: + - string: The human-consumable string + - obj: The accessible object associated with this string + - start: The start offset with respect to entire text, if one exists + - end: The end offset with respect to the entire text, if one exists + - script: The script associated with the accessible object + """ + + self._obj = obj + self._script = script + self._string = string + self._start = start + self._end = end + self._boundingBox = 0, 0, 0, 0 + if script: + self._boundingBox = script.utilities.getTextBoundingBox(obj, start, end) + + def __eq__(self, other): + return other is not None \ + and self._obj == other._obj \ + and self._string == other._string \ + and self._start == other._start \ + and self._end == other._end + + def isSubstringOf(self, other): + """Returns True if this is a substring of other.""" + + if other is None: + return False + + if not (self._obj and other._obj): + return False + + thisBox = self.getBoundingBox() + if thisBox == (0, 0, 0, 0): + return False + + otherBox = other.getBoundingBox() + if otherBox == (0, 0, 0, 0): + return False + + # We get various and sundry results for the bounding box if the implementor + # included newline characters as part of the word or line at offset. Try to + # detect this and adjust the bounding boxes before getting the intersection. + if thisBox[3] != otherBox[3] and self._obj == other._obj: + thisNewLineCount = self._string.count("\n") + if thisNewLineCount and thisBox[3] / thisNewLineCount == otherBox[3]: + thisBox = *thisBox[0:3], otherBox[3] + + if self._script.utilities.intersection(thisBox, otherBox) != thisBox: + return False + + if not (self._string and self._string.strip() in other._string): + return False + + tokens = ["MOUSE REVIEW: '", self._string, "' is substring of '", other._string, "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def getBoundingBox(self): + """Returns the bounding box associated with this context's range.""" + + return self._boundingBox + + def getString(self): + """Returns the string associated with this context.""" + + return self._string + + def present(self): + """Presents this context to the user.""" + + if not self._script: + msg = "MOUSE REVIEW: Not presenting due to lack of script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not self._string: + msg = "MOUSE REVIEW: Not presenting due to lack of string" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + voice = self._script.speechGenerator.voice(obj=self._obj, string=self._string) + string = self._script.utilities.adjustForRepeats(self._string) + + cthulhu.emitRegionChanged(self._obj, self._start, self._end, cthulhu.MOUSE_REVIEW) + self._script.speakMessage(string, voice=voice, interrupt=False) + self._script.displayBrailleMessage(self._string, -1) + return True + + +class _ItemContext: + """Holds all the information of the item at a specified point.""" + + def __init__(self, x=0, y=0, obj=None, boundary=None, frame=None, script=None): + """Initialize the _ItemContext. + + Arguments: + - x: The X coordinate + - y: The Y coordinate + - obj: The accessible object of interest at that coordinate + - boundary: The accessible-text boundary type + - frame: The containing accessible object (often a top-level window) + - script: The script associated with the accessible object + """ + + self._x = x + self._y = y + self._obj = obj + self._boundary = boundary + self._frame = frame + self._script = script + self._string = self._getStringContext() + self._time = time.time() + self._boundingBox = 0, 0, 0, 0 + if script: + self._boundingBox = script.utilities.getBoundingBox(obj) + + def __eq__(self, other): + return other is not None \ + and self._frame == other._frame \ + and self._obj == other._obj \ + and self._string == other._string + + def _treatAsDuplicate(self, prior): + if self._obj != prior._obj or self._frame != prior._frame: + msg = "MOUSE REVIEW: Not a duplicate: different objects" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.getString() and prior.getString() and not self._isSubstringOf(prior): + msg = "MOUSE REVIEW: Not a duplicate: not a substring of" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._x == prior._x and self._y == prior._y: + msg = "MOUSE REVIEW: Treating as duplicate: mouse didn't move" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + interval = self._time - prior._time + if interval > 0.5: + msg = f"MOUSE REVIEW: Not a duplicate: was {interval:.2f}s ago" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + msg = "MOUSE REVIEW: Treating as duplicate" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + def _treatAsSingleObject(self): + if not AXObject.supports_text(self._obj): + return True + + if not self._obj.queryText().characterCount: + return True + + return False + + def _getStringContext(self): + """Returns the _StringContext associated with the specified point.""" + + if not (self._script and self._obj): + return _StringContext(self._obj) + + if self._treatAsSingleObject(): + return _StringContext(self._obj, self._script) + + string, start, end = self._script.utilities.textAtPoint( + self._obj, self._x, self._y, boundary=self._boundary) + if string: + string = self._script.utilities.expandEOCs(self._obj, start, end) + + return _StringContext(self._obj, self._script, string, start, end) + + def _getContainer(self): + roles = [Atspi.Role.DIALOG, + Atspi.Role.FRAME, + Atspi.Role.LAYERED_PANE, + Atspi.Role.MENU, + Atspi.Role.PAGE_TAB, + Atspi.Role.TOOL_BAR, + Atspi.Role.WINDOW] + return AXObject.find_ancestor(self._obj, lambda x: AXObject.get_role(x) in roles) + + def _isSubstringOf(self, other): + """Returns True if this is a substring of other.""" + + return self._string.isSubstringOf(other._string) + + def getObject(self): + """Returns the accessible object associated with this context.""" + + return self._obj + + def getBoundingBox(self): + """Returns the bounding box associated with this context.""" + + x, y, width, height = self._string.getBoundingBox() + if not (width or height): + return self._boundingBox + + return x, y, width, height + + def getString(self): + """Returns the string associated with this context.""" + + return self._string.getString() + + def getTime(self): + """Returns the time associated with this context.""" + + return self._time + + def _isInlineChild(self, prior): + if not self._obj or not prior._obj: + return False + + if AXObject.get_parent(prior._obj) != self._obj: + return False + + if self._treatAsSingleObject(): + return False + + return AXUtilities.is_link(prior._obj) + + def present(self, prior): + """Presents this context to the user.""" + + if self == prior or self._treatAsDuplicate(prior): + msg = "MOUSE REVIEW: Not presenting due to no change" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + interrupt = self._obj and self._obj != prior._obj \ + or math.sqrt((self._x - prior._x)**2 + (self._y - prior._y)**2) > 25 + + if interrupt: + self._script.presentationInterrupt() + + if self._frame and self._frame != prior._frame: + self._script.presentObject(self._frame, + alreadyFocused=True, + inMouseReview=True, + interrupt=True) + + if self._script.utilities.containsOnlyEOCs(self._obj): + msg = "MOUSE REVIEW: Not presenting object which contains only EOCs" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._obj and self._obj != prior._obj and not self._isInlineChild(prior): + priorObj = prior._obj or self._getContainer() + cthulhu.emitRegionChanged(self._obj, mode=cthulhu.MOUSE_REVIEW) + self._script.presentObject(self._obj, priorObj=priorObj, inMouseReview=True) + if self._string.getString() == AXObject.get_name(self._obj): + return True + if not self._script.utilities.isEditableTextArea(self._obj): + return True + if AXUtilities.is_table_cell(self._obj) \ + and self._string.getString() == self._script.utilities.displayedText(self._obj): + return True + + if self._string != prior._string and self._string.present(): + return True + + return True + + +class MouseReviewer: + """Main class for the mouse-review feature.""" + + def __init__(self): + self._active = _settingsManager.getSetting("enableMouseReview") + self._currentMouseOver = _ItemContext() + self._pointer = None + self._workspace = None + self._windows = [] + self._all_windows = [] + self._handlerIds = {} + self._eventListener = Atspi.EventListener.new(self._listener) + self.inMouseEvent = False + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + + if not _mouseReviewCapable: + msg = "MOUSE REVIEW ERROR: Wnck is not available" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + display = Gdk.Display.get_default() + try: + seat = Gdk.Display.get_default_seat(display) + self._pointer = seat.get_pointer() + except AttributeError: + msg = "MOUSE REVIEW ERROR: Gtk+ 3.20 is not available" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + except Exception: + msg = "MOUSE REVIEW ERROR: Exception getting pointer for default seat." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not self._pointer: + msg = "MOUSE REVIEW ERROR: No pointer for default seat." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not self._active: + return + + self.activate() + + def get_bindings(self): + """Returns the mouse-review keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the mouse-review handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the mouse-review input event handlers.""" + + handlers = {} + + handlers["toggleMouseReviewHandler"] = \ + input_event.InputEventHandler( + self.toggle, + cmdnames.MOUSE_REVIEW_TOGGLE) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the mouse-review key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("toggleMouseReviewHandler"))) + + return bindings + + def activate(self): + """Activates mouse review.""" + + if not _mouseReviewCapable: + msg = "MOUSE REVIEW ERROR: Wnck is not available" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + # Set up the initial object as the one with the focus to avoid + # presenting irrelevant info the first time. + obj = cthulhu_state.locusOfFocus + script = None + frame = None + if obj: + script = _scriptManager.getScript(AXObject.get_application(obj), obj) + if script: + frame = script.utilities.topLevelObject(obj) + self._currentMouseOver = _ItemContext(obj=obj, frame=frame, script=script) + + self._eventListener.register("mouse:abs") + screen = Wnck.Screen.get_default() + if screen: + # On first startup windows and workspace are likely to be None, + # but the signals we connect to will get emitted when proper values + # become available; but in case we got disabled and re-enabled we + # have to get the initial values manually. + stacked = screen.get_windows_stacked() + if stacked: + stacked.reverse() + self._all_windows = stacked + self._workspace = screen.get_active_workspace() + if self._workspace: + self._update_workspace_windows() + + i = screen.connect("window-stacking-changed", self._on_stacking_changed) + self._handlerIds[i] = screen + i = screen.connect("active-workspace-changed", self._on_workspace_changed) + self._handlerIds[i] = screen + + self._active = True + + def deactivate(self): + """Deactivates mouse review.""" + + self._eventListener.deregister("mouse:abs") + for key, value in self._handlerIds.items(): + value.disconnect(key) + self._handlerIds = {} + self._workspace = None + self._windows = [] + self._all_windows = [] + + self._active = False + + def getCurrentItem(self): + """Returns the accessible object being reviewed.""" + + if not _mouseReviewCapable: + return None + + if not self._active: + return None + + obj = self._currentMouseOver.getObject() + + if time.time() - self._currentMouseOver.getTime() > 0.1: + tokens = ["MOUSE REVIEW: Treating", obj, "as stale"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + return obj + + def toggle(self, script=None, event=None): + """Toggle mouse reviewing on or off.""" + + if not _mouseReviewCapable: + return + + self._active = not self._active + _settingsManager.setSetting("enableMouseReview", self._active) + + if not self._active: + self.deactivate() + msg = messages.MOUSE_REVIEW_DISABLED + else: + self.activate() + msg = messages.MOUSE_REVIEW_ENABLED + + if cthulhu_state.activeScript: + cthulhu_state.activeScript.presentMessage(msg) + + def _update_workspace_windows(self): + self._windows = [w for w in self._all_windows + if w.is_on_workspace(self._workspace)] + + def _on_stacking_changed(self, screen): + """Callback for Wnck's window-stacking-changed signal.""" + + stacked = screen.get_windows_stacked() + stacked.reverse() + self._all_windows = stacked + if self._workspace: + self._update_workspace_windows() + + def _on_workspace_changed(self, screen, prev_ws=None): + """Callback for Wnck's active-workspace-changed signal.""" + + self._workspace = screen.get_active_workspace() + self._update_workspace_windows() + + def _contains_point(self, obj, x, y, coordType=None): + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + try: + return obj.queryComponent().contains(x, y, coordType) + except Exception: + return False + + def _has_bounds(self, obj, bounds, coordType=None): + """Returns True if the bounding box of obj is bounds.""" + + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + try: + extents = obj.queryComponent().getExtents(coordType) + except Exception: + return False + + return list(extents) == list(bounds) + + def _accessible_window_at_point(self, pX, pY): + """Returns the accessible window at the specified coordinates.""" + + window = None + for w in self._windows: + if w.is_minimized(): + continue + + x, y, width, height = w.get_geometry() + if x <= pX <= x + width and y <= pY <= y + height: + window = w + break + + if not window: + return None + + windowApp = window.get_application() + if not windowApp: + return None + + app = AXUtilities.get_application_with_pid(windowApp.get_pid()) + if not app: + return None + + candidates = [o for o in AXObject.iter_children( + app, lambda x: self._contains_point(x, pX, pY))] + if len(candidates) == 1: + return candidates[0] + + name = window.get_name() + matches = [o for o in candidates if AXObject.get_name(o) == name] + if len(matches) == 1: + return matches[0] + + bbox = window.get_client_window_geometry() + matches = [o for o in candidates if self._has_bounds(o, bbox)] + if len(matches) == 1: + return matches[0] + + return None + + def _on_mouse_moved(self, event): + """Callback for mouse:abs events.""" + + screen, pX, pY = self._pointer.get_position() + window = self._accessible_window_at_point(pX, pY) + tokens = [f"MOUSE REVIEW: Window at ({pX}, {pY}) is", window] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not window: + return + + script = _scriptManager.getScript(AXObject.get_application(window)) + if not script: + return + + if AXObject.is_dead(cthulhu_state.locusOfFocus): + menu = None + elif AXUtilities.is_menu(cthulhu_state.locusOfFocus): + menu = cthulhu_state.locusOfFocus + else: + menu = AXObject.find_ancestor(cthulhu_state.locusOfFocus, AXUtilities.is_menu) + + screen, nowX, nowY = self._pointer.get_position() + if (pX, pY) != (nowX, nowY): + msg = f"MOUSE REVIEW: Pointer moved again: ({nowX}, {nowY})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + obj = script.utilities.descendantAtPoint(menu, pX, pY) \ + or script.utilities.descendantAtPoint(window, pX, pY) + tokens = [f"MOUSE REVIEW: Object at ({pX}, {pY}) is", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + script = _scriptManager.getScript(AXObject.get_application(window), obj) + if menu and obj and not AXObject.find_ancestor(obj, AXUtilities.is_menu): + if script.utilities.intersectingRegion(obj, menu) != (0, 0, 0, 0): + tokens = ["MOUSE REVIEW:", obj, "believed to be under", menu] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + objDocument = script.utilities.getTopLevelDocumentForObject(obj) + if objDocument and script.utilities.inDocumentContent(): + document = script.utilities.activeDocument() + if document != objDocument: + tokens = ["MOUSE REVIEW:", obj, "is not in active document", document] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + screen, nowX, nowY = self._pointer.get_position() + if (pX, pY) != (nowX, nowY): + msg = f"MOUSE REVIEW: Pointer moved again: ({nowX}, {nowY})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + boundary = None + x, y, width, height = self._currentMouseOver.getBoundingBox() + if y <= pY <= y + height and self._currentMouseOver.getString(): + boundary = Atspi.TextBoundaryType.WORD_START + elif obj == self._currentMouseOver.getObject(): + boundary = Atspi.TextBoundaryType.LINE_START + elif AXUtilities.is_selectable(obj): + boundary = Atspi.TextBoundaryType.LINE_START + elif script.utilities.isMultiParagraphObject(obj): + boundary = Atspi.TextBoundaryType.LINE_START + + new = _ItemContext(pX, pY, obj, boundary, window, script) + if new.present(self._currentMouseOver): + self._currentMouseOver = new + + def _listener(self, event): + """Generic listener, mainly to output debugging info.""" + + startTime = time.time() + tokens = ["\nvvvvv PROCESS OBJECT EVENT", event.type, "vvvvv"] + debug.printTokens(debug.LEVEL_INFO, tokens, False) + + if event.type.startswith("mouse:abs"): + self.inMouseEvent = True + self._on_mouse_moved(event) + self.inMouseEvent = False + + msg = f"TOTAL PROCESSING TIME: {time.time() - startTime:.4f}\n" + msg += f"^^^^^ PROCESS OBJECT EVENT {event.type} ^^^^^\n" + debug.printMessage(debug.LEVEL_INFO, msg, False) + + +_reviewer = None +def getReviewer(): + global _reviewer + if _reviewer is None: + _reviewer = MouseReviewer() + return _reviewer diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/notification_presenter.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/notification_presenter.py new file mode 100644 index 0000000..71e0a8b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/notification_presenter.py @@ -0,0 +1,351 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for notification messages""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." \ + "Copyright (c) 2010 Informal Informatica LTDA." +__license__ = "LGPL" + +import time + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import GObject +from gi.repository import Gtk + +from . import cmdnames +from . import debug +from . import guilabels +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu_state + +class NotificationPresenter: + """Provides access to the notification history.""" + + def __init__(self): + self._gui = None + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + self._max_size = 55 + + # The list is arranged with the most recent message being at the end of + # the list. The current index is relative to, and used directly, with the + # python list, i.e. self._notifications[-3] would return the third-to-last + # notification message. + self._notifications = [] + self._current_index = -1 + + def get_bindings(self): + """Returns the notification-presenter keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the notification-presenter handlers.""" + + return self._handlers + + def save_notification(self, message): + """Adds message to the list of notification messages.""" + + tokens = ["NOTIFICATION PRESENTER: Adding '", message, "'."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + to_remove = max(len(self._notifications) - self._max_size + 1, 0) + self._notifications = self._notifications[to_remove:] + self._notifications.append([message, time.time()]) + + def clear_list(self): + """Clears the notifications list.""" + + msg = "NOTIFICATION PRESENTER: Clearing list." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._notifications = [] + self._current_index = -1 + + def _setup_handlers(self): + """Sets up and returns the notification-presenter input event handlers.""" + + handlers = {} + + handlers["present_last_notification"] = \ + input_event.InputEventHandler( + self._present_last_notification, + cmdnames.NOTIFICATION_MESSAGES_LAST) + + handlers["present_next_notification"] = \ + input_event.InputEventHandler( + self._present_next_notification, + cmdnames.NOTIFICATION_MESSAGES_NEXT) + + handlers["present_previous_notification"] = \ + input_event.InputEventHandler( + self._present_previous_notification, + cmdnames.NOTIFICATION_MESSAGES_PREVIOUS) + + handlers["show_notification_list"] = \ + input_event.InputEventHandler( + self._show_notification_list, + cmdnames.NOTIFICATION_MESSAGES_LIST) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the notification-presenter key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("present_last_notification"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("present_next_notification"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("present_previous_notification"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("show_notification_list"))) + + return bindings + + def _timestamp_to_string(self, timestamp): + diff = time.time() - timestamp + if diff < 60: + return messages.secondsAgo(diff) + + if diff < 3600: + minutes = round(diff / 60) + return messages.minutesAgo(minutes) + + if diff < 86400: + hours = round(diff / 3600) + return messages.hoursAgo(hours) + + days = round(diff / 86400) + return messages.daysAgo(days) + + def _present_last_notification(self, script, event=None): + """Presents the last notification.""" + + if not self._notifications: + script.presentMessage(messages.NOTIFICATION_NO_MESSAGES) + return True + + msg = "NOTIFICATION PRESENTER: Presenting last notification." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + message, timestamp = self._notifications[-1] + string = f"{message} {self._timestamp_to_string(timestamp)}" + script.presentMessage(string) + self._current_index = -1 + return True + + def _present_previous_notification(self, script, event=None): + """Presents the previous notification.""" + + if not self._notifications: + script.presentMessage(messages.NOTIFICATION_NO_MESSAGES) + return True + + msg = ( + f"NOTIFICATION PRESENTER: Presenting previous notification. " + f"Current index: {self._current_index}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # This is the first (oldest) message in the list. + if self._current_index == 0 : + script.presentMessage(messages.NOTIFICATION_LIST_TOP) + message, timestamp = self._notifications[self._current_index] + else: + try: + index = self._current_index - 1 + message, timestamp = self._notifications[index] + self._current_index -= 1 + except IndexError: + msg = "NOTIFICATION PRESENTER: Handling IndexError exception." + debug.printMessage(debug.LEVEL_INFO, msg, True) + script.presentMessage(messages.NOTIFICATION_LIST_TOP) + message, timestamp = self._notifications[self._current_index] + + string = f"{message} {self._timestamp_to_string(timestamp)}" + script.presentMessage(string) + return True + + def _present_next_notification(self, script, event=None): + """Presents the next notification.""" + + if not self._notifications: + script.presentMessage(messages.NOTIFICATION_NO_MESSAGES) + return True + + msg = ( + f"NOTIFICATION PRESENTER: Presenting next notification. " + f"Current index: {self._current_index}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # This is the last (newest) message in the list. + if self._current_index == -1: + script.presentMessage(messages.NOTIFICATION_LIST_BOTTOM) + message, timestamp = self._notifications[self._current_index] + else: + try: + index = self._current_index + 1 + message, timestamp = self._notifications[index] + self._current_index += 1 + except IndexError: + msg = "NOTIFICATION PRESENTER: Handling IndexError exception." + debug.printMessage(debug.LEVEL_INFO, msg, True) + script.presentMessage(messages.NOTIFICATION_LIST_BOTTOM) + message, timestamp = self._notifications[self._current_index] + + string = f"{message} {self._timestamp_to_string(timestamp)}" + script.presentMessage(string) + return True + + def _show_notification_list(self, script, event=None): + """Opens a dialog with a list of the notifications.""" + + if not self._notifications: + script.presentMessage(messages.NOTIFICATION_NO_MESSAGES) + return True + + msg = "NOTIFICATION PRESENTER: Showing notification list." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + rows = [(message, self._timestamp_to_string(timestamp)) \ + for message, timestamp in reversed(self._notifications)] + title = guilabels.notifications_count(len(self._notifications)) + column_headers = [guilabels.NOTIFICATIONS_COLUMN_HEADER, + guilabels.NOTIFICATIONS_RECEIVED_TIME] + self._gui = NotificationListGUI(script, title, column_headers, rows) + self._gui.show_gui() + return True + + def on_dialog_destroyed(self): + """Handler for the 'destroyed' signal of the dialog.""" + + self._gui = None + +class NotificationListGUI: + """The dialog containing the notifications list.""" + + def __init__(self, script, title, column_headers, rows): + self._script = script + self._model = None + self._gui = self._create_dialog(title, column_headers, rows) + + def _create_dialog(self, title, column_headers, rows): + dialog = Gtk.Dialog(title, + None, + Gtk.DialogFlags.MODAL, + (Gtk.STOCK_CLEAR, Gtk.ResponseType.APPLY, + Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)) + dialog.set_default_size(600, 400) + + grid = Gtk.Grid() + content_area = dialog.get_content_area() + content_area.add(grid) + + scrolled_window = Gtk.ScrolledWindow() + grid.add(scrolled_window) + + tree = Gtk.TreeView() + tree.set_hexpand(True) + tree.set_vexpand(True) + scrolled_window.add(tree) + + cols = len(column_headers) * [GObject.TYPE_STRING] + for i, header in enumerate(column_headers): + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(header, cell, text=i) + tree.append_column(column) + if header: + column.set_sort_column_id(i) + + self._model = Gtk.ListStore(*cols) + for row in rows: + row_iter = self._model.append(None) + for i, cell in enumerate(row): + self._model.set_value(row_iter, i, cell) + + tree.set_model(self._model) + dialog.connect("response", self.on_response) + return dialog + + def on_response(self, dialog, response): + """The handler for the 'response' signal.""" + + if response == Gtk.ResponseType.CLOSE: + self._gui.destroy() + return + + if response == Gtk.ResponseType.APPLY and self._model is not None: + self._model.clear() + getPresenter().clear_list() + self._script.presentMessage(messages.NOTIFICATION_NO_MESSAGES) + time.sleep(1) + self._gui.destroy() + + def show_gui(self): + """Shows the notifications list dialog.""" + + self._gui.show_all() + time_stamp = cthulhu_state.lastInputEvent.timestamp + if time_stamp == 0: + time_stamp = Gtk.get_current_event_time() + self._gui.present_with_time(time_stamp) + +_presenter = None +def getPresenter(): + """Returns the Notification Presenter""" + + global _presenter + if _presenter is None: + _presenter = NotificationPresenter() + return _presenter diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_navigator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_navigator.py new file mode 100644 index 0000000..bc01f6b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_navigator.py @@ -0,0 +1,331 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides ability to navigate objects hierarchically.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 The Cthulhu Team" +__license__ = "LGPL" + +from . import cmdnames +from . import debug +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu +from . import cthulhu_state +from .ax_event_synthesizer import AXEventSynthesizer +from .ax_object import AXObject +from .ax_utilities import AXUtilities + + +class ObjectNavigator: + """Provides ability to navigate objects hierarchically.""" + + def __init__(self): + self._navigator_focus = None + self._last_navigator_focus = None + self._last_locus_of_focus = None + self._simplify = True + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + + def get_bindings(self): + """Returns the object-navigator keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the object-navigator handlers.""" + + return self._handlers + + def _setup_bindings(self): + """Sets up and returns the object-navigator key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "Up", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("object_navigator_up"))) + + bindings.add( + keybindings.KeyBinding( + "Down", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("object_navigator_down"))) + + bindings.add( + keybindings.KeyBinding( + "Right", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("object_navigator_next"))) + + bindings.add( + keybindings.KeyBinding( + "Left", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("object_navigator_previous"))) + + bindings.add( + keybindings.KeyBinding( + "Return", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("object_navigator_perform_action"))) + + bindings.add( + keybindings.KeyBinding( + "s", + keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_MODIFIER_MASK, + self._handlers.get("object_navigator_toggle_simplify"))) + + return bindings + + def _setup_handlers(self): + """Sets up and returns the object-navigator input event handlers.""" + + handlers = {} + + handlers["object_navigator_up"] = \ + input_event.InputEventHandler( + self.up, + cmdnames.NAVIGATOR_UP) + + handlers["object_navigator_down"] = \ + input_event.InputEventHandler( + self.down, + cmdnames.NAVIGATOR_DOWN) + + handlers["object_navigator_next"] = \ + input_event.InputEventHandler( + self.next, + cmdnames.NAVIGATOR_NEXT) + + handlers["object_navigator_previous"] = \ + input_event.InputEventHandler( + self.previous, + cmdnames.NAVIGATOR_PREVIOUS) + + handlers["object_navigator_perform_action"] = \ + input_event.InputEventHandler( + self.perform_action, + cmdnames.NAVIGATOR_PERFORM_ACTION) + + handlers["object_navigator_toggle_simplify"] = \ + input_event.InputEventHandler( + self.toggle_simplify, + cmdnames.NAVIGATOR_TOGGLE_SIMPLIFIED) + + return handlers + + def _include_in_simple_navigation(self, obj): + """Returns True if obj should be included in simple navigation.""" + + return AXUtilities.is_paragraph(obj) + + def _exclude_from_simple_navigation(self, script, obj): + """Returns True if obj should be excluded from simple navigation.""" + + if self._include_in_simple_navigation(obj): + tokens = ["OBJECT NAVIGATOR: Not excluding", obj, ": explicit inclusion"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + # isLayoutOnly should catch things that really should be skipped. + # + # You do not want to exclude all sections because they may be focusable, e.g. + #
foo
should not be excluded, despite the poor authoring. + # + # You do not want to exclude table cells and headers because it will make the + # selectable items in tables non-navigable (e.g. the mail folders in Evolution) + if script.utilities.isLayoutOnly(obj): + tokens = ["OBJECT NAVIGATOR: Excluding", obj, ": is layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + tokens = ["OBJECT NAVIGATOR: Not excluding", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + def _children(self, script, obj): + """Returns a list of children for obj, taking simple navigation into account.""" + + if not AXObject.get_child_count(obj): + return [] + + children = list(AXObject.iter_children(obj)) + if not self._simplify: + return children + + # Add the children of excluded objects to our list of children. + functional_children = [] + for child in children: + if self._exclude_from_simple_navigation(script, child): + functional_children.extend(self._children(script, child)) + else: + functional_children.append(child) + + return functional_children + + def _parent(self, script, obj): + """Returns the parent for obj, taking simple navigation into account.""" + + parent = AXObject.get_parent(obj) + if not self._simplify: + return parent + + # The first non-excluded ancestor is the functional parent. + while parent is not None and self._exclude_from_simple_navigation(script, parent): + parent = AXObject.get_parent(parent) + + return parent + + def _set_navigator_focus(self, obj): + """Changes the navigator focus, storing the previous focus.""" + + self._last_navigator_focus = self._navigator_focus + self._navigator_focus = obj + + def update(self): + """Updates the navigator focus to Cthulhu's object of interest.""" + + mode, region = cthulhu.getActiveModeAndObjectOfInterest() + obj = region or cthulhu_state.locusOfFocus + if self._last_locus_of_focus == obj or (region is None and mode == cthulhu.FLAT_REVIEW): + return + + self._navigator_focus = obj + self._last_locus_of_focus = obj + + def present(self, script): + """Presents the current navigator focus to the user.""" + + tokens = ["OBJECT NAVIGATOR: Presenting", self._navigator_focus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.emitRegionChanged(self._navigator_focus, mode=cthulhu.OBJECT_NAVIGATOR) + script.presentObject(self._navigator_focus, priorObj=self._last_navigator_focus) + + def up(self, script, event=None): + """Moves the navigator focus to the parent of the current focus.""" + + self.update() + parent = self._parent(script, self._navigator_focus) + if parent is not None: + self._set_navigator_focus(parent) + self.present(script) + else: + script.presentMessage(messages.NAVIGATOR_NO_PARENT) + + def down(self, script, event=None): + """Moves the navigator focus to the first child of the current focus.""" + + self.update() + children = self._children(script, self._navigator_focus) + if not children: + script.presentMessage(messages.NAVIGATOR_NO_CHILDREN) + return + + self._set_navigator_focus(children[0]) + self.present(script) + + def next(self, script, event=None): + """Moves the navigator focus to the next sibling of the current focus.""" + + self.update() + parent = self._parent(script, self._navigator_focus) + if parent is None: + script.presentMessage(messages.NAVIGATOR_NO_NEXT) + return + + siblings = self._children(script, parent) + if self._navigator_focus in siblings: + index = siblings.index(self._navigator_focus) + if index < len(siblings) - 1: + self._set_navigator_focus(siblings[index+1]) + self.present(script) + else: + script.presentMessage(messages.NAVIGATOR_NO_NEXT) + else: + self._set_navigator_focus(parent) + self.present(script) + + def previous(self, script, event=None): + """Moves the navigator focus to the previous sibling of the current focus.""" + + self.update() + parent = self._parent(script, self._navigator_focus) + if parent is None: + script.presentMessage(messages.NAVIGATOR_NO_PREVIOUS) + return + + siblings = self._children(script, parent) + if self._navigator_focus in siblings: + index = siblings.index(self._navigator_focus) + if index > 0: + self._set_navigator_focus(siblings[index-1]) + self.present(script) + else: + script.presentMessage(messages.NAVIGATOR_NO_PREVIOUS) + else: + self._set_navigator_focus(parent) + self.present(script) + + def toggle_simplify(self, script, event=None): + """Toggles simplified navigation.""" + + self._simplify = not self._simplify + if self._simplify: + script.presentMessage(messages.NAVIGATOR_SIMPLIFIED_ENABLED) + else: + script.presentMessage(messages.NAVIGATOR_SIMPLIFIED_DISABLED) + return True + + def perform_action(self, script, event=None): + """Attempts to click on the current focus.""" + if AXEventSynthesizer.try_all_clickable_actions(self._navigator_focus): + return True + + AXEventSynthesizer.click_object(self._navigator_focus, 1) + return True + + +_navigator = None +def getNavigator(): + """Returns the Object Navigator""" + + global _navigator + if _navigator is None: + _navigator = ObjectNavigator() + return _navigator diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_properties.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_properties.py new file mode 100644 index 0000000..77e90e7 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/object_properties.py @@ -0,0 +1,672 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Propeerties of accessible objects. These have been put in their own module +so that we can present them in the correct language when users change the +language on the fly without having to reload a bunch of modules.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team" +__license__ = "LGPL" + +from .cthulhu_i18n import _, C_ + +# Translators: this is the action name for the 'toggle' action. It must be the +# same string used in the *.po file for gail. +ACTION_TOGGLE = _("toggle") + +# Translators: this is a indication of the focused icon and the count of the +# total number of icons within an icon panel. An example of an icon panel is +# the Nautilus folder view. +ICON_INDEX_SPEECH = _("on %(index)d of %(total)d") + +# Translators: this refers to the position of an item in a list or group of +# objects, such as menu items in a menu, radio buttons in a radio button group, +# combobox item in a combobox, etc. +GROUP_INDEX_SPEECH = _("%(index)d of %(total)d") + +# Translators: this refers to the position of an item in a list for which the +# size is unknown. Examples include unlimited scrolling news/article feeds +# on social media sites, and message lists on services such as gmail where +# you're currently viewing messages 1-100 out of some huge, unspecified +# number. Normally Cthulhu announces both the position of the item and the +# total number (e.g. "3 of 5"). This is the corresponding message for the +# unknown-count scenario. +GROUP_INDEX_TOTAL_UNKNOWN_SPEECH = _("item %(index)d") + +# Translators: This message describes a list item in a document. Nesting level +# is how "deep" the item is (e.g., a level of 2 represents a list item inside a +# list that's inside another list). +NESTING_LEVEL_SPEECH = _("Nesting level %d") + +# Translators: This message describes a list item in a document. Nesting level +# is how "deep" the item is (e.g., a level of 2 represents a list item inside a +# list that's inside another list). This string is specifically for braille. +# Because braille displays lack real estate, we're using a shorter string than +# we use for speech. +NESTING_LEVEL_BRAILLE = _("LEVEL %d") + +# Translators: This represents the depth of a node in a TreeView (i.e. how many +# ancestors the node has). This is the spoken version. +NODE_LEVEL_SPEECH = _("tree level %d") + +# Translators: This represents the depth of a node in a TreeView (i.e. how many +# ancestors the node has). This is the braille version. +NODE_LEVEL_BRAILLE = _("TREE LEVEL %d") + +# Translators: In web content, authors can identify an element which contains +# detailed information about another element. For instance, for a password +# field, there may be a list of requirements (number of characters, number of +# special symbols, etc.). For an image, there may be an extended description +# before or after the image. Often there are visual clues connecting the +# detailed information to its related object. We need to convey this non-visually. +# This relationship will be presented for the object containing the details, e.g. +# when arrowing into or out of it. The string substitution is for the object to +# which the detailed information applies. For instance, when navigating into +# the details for an image named Pythagorean Theorem, Cthulhu would present: +# "details for Pythagorean Theorem image". +# See https://w3c.github.io/aria/#aria-details +RELATION_DETAILS_FOR = _("details for %s") + +# Translators: In web content, authors can identify an element which contains +# detailed information about another element. For instance, for a password +# field, there may be a list of requirements (number of characters, number of +# special symbols, etc.). For an image, there may be an extended description +# before or after the image. Often there are visual clues connecting the +# detailed information to its related object. We need to convey this non-visually. +# This relationship will be presented for the object which has details to tell +# the user the type of object where the details can be found so that they can +# more quickly navigate to it. The string substitution is for the object to +# which the detailed information applies. For instance, when navigating to +# a password field which has details in a list named "Requirements", Cthulhu would +# present: "has details in Requirements list". +# See https://w3c.github.io/aria/#aria-details +RELATION_HAS_DETAILS = _("has details in %s") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a container with a proposed change. This change can +# include the insertion and/or deletion of content, and would typically be seen +# in a collaborative editor, such as in Google Docs. +ROLE_CONTENT_SUGGESTION = C_("role", "suggestion") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The reason for including the editable state as part of the role is to make it +# possible for users to quickly identify combo boxes in which a value can be +# typed or arrowed to. +ROLE_EDITABLE_COMBO_BOX = _("editable combo box") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role is to describe elements in web content which have the contenteditable +# attribute set to true, indicating that the element can be edited by the user. +ROLE_EDITABLE_CONTENT = _("editable content") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The feed role is a scrollable list of articles where scrolling may cause +# articles to be added to or removed from either end of the list. +# https://w3c.github.io/aria/#feed +ROLE_FEED = C_("role", "feed") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The figure role is a perceivable section of content that typically contains a +# graphical document, images, code snippets, or example text. +# https://w3c.github.io/aria/#figure +ROLE_FIGURE = C_("role", "figure") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the abstract in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-abstract +ROLE_ABSTRACT = C_("role", "abstract") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the acknowledgments in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-acknowledgments +ROLE_ACKNOWLEDGMENTS = C_("role", "acknowledgments") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the afterword in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-afterword +ROLE_AFTERWORD = C_("role", "afterword") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the appendix in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-appendix +ROLE_APPENDIX = C_("role", "appendix") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a bibliography entry in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-biblioentry +ROLE_BIBLIOENTRY = C_("role", "bibliography entry") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the bibliography in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-bibliography +ROLE_BIBLIOGRAPHY = C_("role", "bibliography") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a chapter in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-chapter +ROLE_CHAPTER = C_("role", "chapter") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the colophon in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-colophon +ROLE_COLOPHON = C_("role", "colophon") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the conclusion in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-conclusion +ROLE_CONCLUSION = C_("role", "conclusion") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the cover in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-cover +ROLE_COVER = C_("role", "cover") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a single credit in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-credit +ROLE_CREDIT = C_("role", "credit") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the credits in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-credits +ROLE_CREDITS = C_("role", "credits") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the dedication in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-dedication +ROLE_DEDICATION = C_("role", "dedication") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a single endnote in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-endnote +ROLE_ENDNOTE = C_("role", "endnote") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the endnotes in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-endnotes +ROLE_ENDNOTES = C_("role", "endnotes") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the epigraph in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-epigraph +ROLE_EPIGRAPH = C_("role", "epigraph") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the epilogue in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-epilogue +ROLE_EPILOGUE = C_("role", "epilogue") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the errata in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-errata +ROLE_ERRATA = C_("role", "errata") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to an example in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-example +ROLE_EXAMPLE = C_("role", "example") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the foreword in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-foreword +ROLE_FOREWORD = C_("role", "foreword") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the glossary in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-glossary +ROLE_GLOSSARY = C_("role", "glossary") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the index in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-index +ROLE_INDEX = C_("role", "index") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the introduction in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-introduction +ROLE_INTRODUCTION = C_("role", "introduction") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a pagebreak in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-pagebreak +ROLE_PAGEBREAK = C_("role", "page break") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a page list in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-pagelist +ROLE_PAGELIST = C_("role", "page list") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a named part in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-part +ROLE_PART = C_("role", "part") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the preface in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-preface +ROLE_PREFACE = C_("role", "preface") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the prologue in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-prologue +ROLE_PROLOGUE = C_("role", "prologue") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a pullquote in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-pullquote +ROLE_PULLQUOTE = C_("role", "pullquote") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to a questions-and-answers section in a digitally-published +# document. https://w3c.github.io/dpub-aria/#doc-qna +# In English, "QNA" is generally recognized by native speakers. If your language +# lacks the equivalent, please prefer the shortest phrase which clearly conveys +# the meaning. +ROLE_QNA = C_("role", "QNA") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the subtitle in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-subtitle +ROLE_SUBTITLE = C_("role", "subtitle") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# This role refers to the table of contents in a digitally-published document. +# https://w3c.github.io/dpub-aria/#doc-toc +ROLE_TOC = C_("role", "table of contents") + +# Translators: The 'h' in this string represents a heading level attribute for +# content that you might find in something such as HTML content (e.g.,

). +# The translated form is meant to be a single character followed by a numeric +# heading level, where the single character is to indicate 'heading'. +ROLE_HEADING_LEVEL_BRAILLE = _("h%d") + +# Translators: The %(level)d is in reference to a heading level in HTML (e.g., +# For

, the level is 3) and the %(role)s is in reference to a previously +# translated rolename for the heading. +ROLE_HEADING_LEVEL_SPEECH = _("%(role)s level %(level)d") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The reason we include the orientation as part of the role is because in some +# applications and toolkits, it can dictate which keyboard keys should be used +# to modify the value of the widget. +ROLE_SCROLL_BAR_HORIZONTAL = _("horizontal scroll bar") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The reason we include the orientation as part of the role is because in some +# applications and toolkits, it can dictate which keyboard keys should be used +# to modify the value of the widget. +ROLE_SCROLL_BAR_VERTICAL = _("vertical scroll bar") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# A slider is a widget which looks like a bar and displays a value as a range. +# A common example of a slider can be found in UI for modifying volume levels. +# The reason we include the orientation as part of the role is because in some +# applications and toolkits, it can dictate which keyboard keys should be used +# to modify the value of the widget. +ROLE_SLIDER_HORIZONTAL = _("horizontal slider") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# A slider is a widget which looks like a bar and displays a value as a range. +# A common example of a slider can be found in UI for modifying volume levels. +# The reason we include the orientation as part of the role is because in some +# applications and toolkits, it can dictate which keyboard keys should be used +# to modify the value of the widget. +ROLE_SLIDER_VERTICAL = _("vertical slider") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# A splitter is a bar that divides a container into two parts. It is often, but +# not necessarily, user resizable. A common example of a splitter can be found +# in email applications, where there is a container on the left which holds a +# list of all the mail folders and a container on the right which lists all of +# the messages in the selected folder. The bar which you click on and drag to +# resize these containers is the splitter. The reason we include the orientation +# as part of the role is because in some applications and toolkits, it can +# dictate which keyboard keys should be used to modify the value of the widget. +ROLE_SPLITTER_HORIZONTAL = _("horizontal splitter") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# A splitter is a bar that divides a container into two parts. It is often, but +# not necessarily, user resizable. A common example of a splitter can be found +# in email applications, where there is a container on the left which holds a +# list of all the mail folders and a container on the right which lists all of +# the messages in the selected folder. The bar which you click on and drag to +# resize these containers is the splitter. The reason we include the orientation +# as part of the role is because in some applications and toolkits, it can +# dictate which keyboard keys should be used to modify the value of the widget. +ROLE_SPLITTER_VERTICAL = _("vertical splitter") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "switch" role is a "light switch" style toggle, such as can be seen in +# https://developer.gnome.org/gtk3/stable/GtkSwitch.html +ROLE_SWITCH = C_("role", "switch") + +# Translators: This is an alternative name for the parent object of a series +# of icons. +ROLE_ICON_PANEL = _("Icon panel") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "banner" role is defined in the ARIA specification as "A region that +# contains mostly site-oriented content, rather than page-specific content." +# See https://www.w3.org/TR/wai-aria-1.1/#banner +ROLE_LANDMARK_BANNER = C_("role", "banner") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "complementary" role is defined in the ARIA specification as "A supporting +# section of the document, designed to be complementary to the main content at a +# similar level in the DOM hierarchy, but remains meaningful when separated from +# the main content." See https://www.w3.org/TR/wai-aria-1.1/#complementary +ROLE_LANDMARK_COMPLEMENTARY = C_("role", "complementary content") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "contentinfo" role is defined in the ARIA specification as "A large +# perceivable region that contains information about the parent document. +# Examples of information included in this region of the page are copyrights and +# links to privacy statements." See https://www.w3.org/TR/wai-aria-1.1/#contentinfo +ROLE_LANDMARK_CONTENTINFO = C_("role", "information") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "main" role is defined in the ARIA specification as "The main content of +# a document." See https://www.w3.org/TR/wai-aria-1.1/#main +ROLE_LANDMARK_MAIN = C_("role", "main content") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "navigation" role is defined in the ARIA specification as "A collection of +# navigational elements (usually links) for navigating the document or related +# documents." See https://www.w3.org/TR/wai-aria-1.1/#navigation +ROLE_LANDMARK_NAVIGATION = C_("role", "navigation") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "region" role is defined in the ARIA specification as "A perceivable +# section containing content that is relevant to a specific, author-specified +# purpose and sufficiently important that users will likely want to be able to +# navigate to the section easily and to have it listed in a summary of the page." +# See https://www.w3.org/TR/wai-aria-1.1/#region +ROLE_LANDMARK_REGION = C_("role", "region") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The "search" role is defined in the ARIA specification as "A landmark region +# that contains a collection of items and objects that, as a whole, combine to +# create a search facility." See https://www.w3.org/TR/wai-aria-1.1/#search +ROLE_LANDMARK_SEARCH = C_("role", "search") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# The reason for including the visited state as part of the role is to make it +# possible for users to quickly identify if the link is associated with content +# already read. +ROLE_VISITED_LINK = _("visited link") + +# Translators: This string should be treated as a role describing an object. +# Examples of roles include "checkbox", "radio button", "paragraph", and "link." +# A menu button is button widget that causes a menu to appear when the user +# activates the button. +ROLE_MENU_BUTTON = _("menu button") + +# Translators: This string refers to a row or column whose sort-order has been set +# to ascending. +SORT_ORDER_ASCENDING = _("sorted ascending") + +# Translators: This string refers to a row or column whose sort-order has been set +# to descending. +SORT_ORDER_DESCENDING = _("sorted descending") + +# Translators: This string refers to a row or column whose sort-order has been set, +# but the nature of the sort order is unknown or something other than ascending or +# descending. +SORT_ORDER_OTHER = _("sorted") + +# Translators: This is a state which applies to elements in document content +# which have an "onClick" action. +STATE_CLICKABLE = _("clickable") + +# Translators: This is a state which applies to items which can be expanded +# or collapsed such as combo boxes and nodes/groups in a treeview. Collapsed +# means the item's children are not showing; expanded means they are. +STATE_COLLAPSED = _("collapsed") + +# Translators: This is a state which applies to items which can be expanded +# or collapsed such as combo boxes and nodes/groups in a treeview. Collapsed +# means the item's children are not showing; expanded means they are. +STATE_EXPANDED = _("expanded") + +# Translators: This is a state which applies to elements in document content +# which have a longdesc attribute. http://www.w3.org/TR/WCAG20-TECHS/H45.html +STATE_HAS_LONGDESC = _("has long description") + +# Translators: This is a state which applies to the orientation of widgets +# such as sliders and scroll bars. +STATE_HORIZONTAL = _("horizontal") + +# Translators: This is a state which applies to the orientation of widgets +# such as sliders and scroll bars. +STATE_VERTICAL = _("vertical") + +# Translators: This is a state which applies to a check box. +STATE_CHECKED = C_("checkbox", "checked") + +# Translators: This is a state which applies to a check box. +STATE_NOT_CHECKED = C_("checkbox", "not checked") + +# Translators: This is a state which applies to a switch. For an example of +# a switch, see https://developer.gnome.org/gtk3/stable/GtkSwitch.html +STATE_ON_SWITCH = C_("switch", "on") + +# Translators: This is a state which applies to a switch. For an example of +# a switch, see https://developer.gnome.org/gtk3/stable/GtkSwitch.html +STATE_OFF_SWITCH = C_("switch", "off") + +# Translators: This is a state which applies to a check box. +STATE_PARTIALLY_CHECKED = C_("checkbox", "partially checked") + +# Translators: This is a state which applies to a toggle button. +STATE_PRESSED = C_("togglebutton", "pressed") + +# Translators: This is a state which applies to a toggle button. +STATE_NOT_PRESSED = C_("togglebutton", "not pressed") + +# Translators: This is a state which applies to an item or option +# in a selectable list. +STATE_UNSELECTED_LIST_ITEM = C_("listitem", "not selected") + +# Translators: This is a state which applies to a radio button. +STATE_SELECTED_RADIO_BUTTON = C_("radiobutton", "selected") + +# Translators: This is a state which applies to a radio button. +STATE_UNSELECTED_RADIO_BUTTON = C_("radiobutton", "not selected") + +# Translators: This is a state which applies to a table cell. +STATE_UNSELECTED_TABLE_CELL = C_("tablecell", "not selected") + +# Translators: This is a state which applies to a link. +STATE_VISITED = C_("link state", "visited") + +# Translators: This is a state which applies to a link. +STATE_UNVISITED = C_("link state", "unvisited") + +# Translators: This state represents an item on the screen that has been set +# insensitive (or grayed out). +STATE_INSENSITIVE_SPEECH = _("grayed") + +# Translators: This state represents an item on the screen that has been set +# insensitive (or grayed out). +STATE_INSENSITIVE_BRAILLE = _("grayed") + +# Translators: Certain objects (such as form controls on web pages) can have +# STATE_EDITABLE set to inform the user that this field can be filled out. +# It is assumed that form fields will be editable; if they lack this state, +# we need to present that information to the user. This string is the spoken +# version. +STATE_READ_ONLY_SPEECH = C_("text", "read only") + +# Translators: Certain objects (such as form controls on web pages) can have +# STATE_EDITABLE set to inform the user that this field can be filled out. +# It is assumed that form fields will be editable; if they lack this state, +# we need to present that information to the user. This string is the braille +# version. (Because braille displays have limited real estate, we abbreviate.) +STATE_READ_ONLY_BRAILLE = C_("text", "rdonly") + +# Translators: Certain objects (such as form controls on web pages) can have +# STATE_REQUIRED set to inform the user that this field must be filled out. +STATE_REQUIRED_SPEECH = _("required") + +# Translators: Certain objects (such as form controls on web pages) can have +# STATE_REQUIRED set to inform the user that this field must be filled out. +STATE_REQUIRED_BRAILLE = _("required") + +# Translators: "multi-select" refers to a web form list in which more than +# one item can be selected at a time. +STATE_MULTISELECT_SPEECH = _("multi-select") + +# Translators: STATE_INVALID_ENTRY indicates that the associated object, such +# as a form field, has an error. The following string is spoken when all we +# know is that an error has occurred, but not the type of error. +STATE_INVALID_SPEECH = C_("error", "invalid entry") + +# Translators: STATE_INVALID_ENTRY indicates that the associated object, such +# as a form field, has an error. The following string is displayed in braille +# when all we know is that an error has occurred, but not the type of error. +# We prefer a smaller string than in speech because braille displays have a +# limited size. +STATE_INVALID_BRAILLE = C_("error", "invalid") + +# Translators: STATE_INVALID_ENTRY indicates that the associated object, such +# as a form field, has an error. The following string is spoken when the error +# is related to spelling. +STATE_INVALID_SPELLING_SPEECH = C_("error", "invalid spelling") + +# Translators: STATE_INVALID_ENTRY indicates that the associated object, such +# as a form field, has an error. The following string is displayed in braille +# when the error is related to spelling. We prefer a smaller string than in +# speech because braille displays have a limited size. +STATE_INVALID_SPELLING_BRAILLE = C_("error", "spelling") + +# Translators: STATE_INVALID_ENTRY indicates that the associated object, such +# as a form field, has an error. The following string is spoken when the error +# is related to grammar. +STATE_INVALID_GRAMMAR_SPEECH = C_("error", "invalid grammar") + +# Translators: STATE_INVALID_ENTRY indicates that the associated object, such +# as a form field, has an error. The following string is displayed in braille +# when the error is related to grammar. We prefer a smaller string than in +# speech because braille displays have a limited size. +STATE_INVALID_GRAMMAR_BRAILLE = C_("error", "grammar") + +# TODO: Look at why we're doing this as lists. + +CHECK_BOX_INDICATORS_SPEECH = \ + [STATE_NOT_CHECKED, STATE_CHECKED, STATE_PARTIALLY_CHECKED] +EXPANSION_INDICATORS_SPEECH = \ + [STATE_COLLAPSED, STATE_EXPANDED] +INVALID_INDICATORS_SPEECH = \ + [STATE_INVALID_SPEECH, + STATE_INVALID_SPELLING_SPEECH, + STATE_INVALID_GRAMMAR_SPEECH] +RADIO_BUTTON_INDICATORS_SPEECH = \ + [STATE_UNSELECTED_RADIO_BUTTON, STATE_SELECTED_RADIO_BUTTON] + +SWITCH_INDICATORS_SPEECH = [STATE_OFF_SWITCH, STATE_ON_SWITCH] +TOGGLE_BUTTON_INDICATORS_SPEECH = \ + [STATE_NOT_PRESSED, STATE_PRESSED] + +CHECK_BOX_INDICATORS_BRAILLE = ["< >", "", "<->"] +EXPANSION_INDICATORS_BRAILLE = [STATE_COLLAPSED, STATE_EXPANDED] +INVALID_INDICATORS_BRAILLE = [STATE_INVALID_BRAILLE, + STATE_INVALID_SPELLING_BRAILLE, + STATE_INVALID_GRAMMAR_BRAILLE] +RADIO_BUTTON_INDICATORS_BRAILLE = ["& y", "&=y"] +SWITCH_INDICATORS_BRAILLE = ["& y", "&=y"] +TOGGLE_BUTTON_INDICATORS_BRAILLE = ["& y", "&=y"] + +TABLE_CELL_DELIMITER_BRAILLE = " " +EOL_INDICATOR_BRAILLE = " $l" + +CHECK_BOX_INDICATORS_SOUND = ["not_checked", "checked", "partially_checked"] +EXPANSION_INDICATORS_SOUND = ["collapsed", "expanded"] +INVALID_INDICATORS_SOUND = ["invalid", "invalid_spelling", "invalid_grammar"] +RADIO_BUTTON_INDICATORS_SOUND = ["unselected", "selected"] +SWITCH_INDICATORS_SOUND = ["off", "on"] +TOGGLE_BUTTON_INDICATORS_SOUND = ["not_pressed", "pressed"] +STATE_CLICKABLE_SOUND = "clickable" +STATE_HAS_LONGDESC_SOUND = "haslongdesc" +STATE_INSENSITIVE_SOUND = "insensitive" +STATE_MULTISELECT_SOUND = "multiselect" +STATE_READ_ONLY_SOUND = "readonly" +STATE_REQUIRED_SOUND = "required" +STATE_VISITED_SOUND = "visited" diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/phonnames.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/phonnames.py new file mode 100644 index 0000000..9032ac7 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/phonnames.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides getPhoneticName method that maps each letter of the +alphabet into its localized phonetic equivalent.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +from .cthulhu_i18n import _ + +# Translators: this is a structure to assist in the generation of +# spoken military-style spelling. For example, 'abc' becomes 'alpha +# bravo charlie'. +# +# It is a simple structure that consists of pairs of +# +# letter : word(s) +# +# where the letter and word(s) are separate by colons and each +# pair is separated by commas. For example, we see: +# +# a : alpha, b : bravo, c : charlie, +# +# And so on. The complete set should consist of all the letters from +# the alphabet for your language paired with the common +# military/phonetic word(s) used to describe that letter. +# +# The Wikipedia entry +# http://en.wikipedia.org/wiki/NATO_phonetic_alphabet has a few +# interesting tidbits about local conventions in the sections +# "Additions in German, Danish and Norwegian" and "Variants". +# +__phonlist = _("a : alpha, b : bravo, c : charlie, " + "d : delta, e : echo, f : foxtrot, " + "g : golf, h : hotel, i : india, " + "j : juliet, k : kilo, l : lima, " + "m : mike, n : november, o : oscar, " + "p : papa, q : quebec, r : romeo, " + "s : sierra, t : tango, u : uniform, " + "v : victor, w : whiskey, x : xray, " + "y : yankee, z : zulu") + +__phonnames = {} + +for __pair in __phonlist.split(','): + __w = __pair.split(':') + __phonnames [__w[0].strip()] = __w[1].strip() + +def getPhoneticName(character): + """Given a character, return its phonetic name, which is typically + the 'military' term used for the character. + + Arguments: + - character: the character to get the military name for + + Returns a string representing the military name for the character + """ + + return __phonnames.get(character, character) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin.py new file mode 100644 index 0000000..6f7f7fb --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 Stormux +# +# 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. + +"""Base class for Cthulhu plugins using pluggy.""" + +import os +import logging + +# Import pluggy for hook specifications +try: + import pluggy + cthulhu_hookimpl = pluggy.HookimplMarker("cthulhu") + PLUGGY_AVAILABLE = True + logging.getLogger(__name__).info("Successfully imported pluggy") +except ImportError: + # Fallback if pluggy is not available + def cthulhu_hookimpl(func=None, **kwargs): + """Fallback decorator when pluggy is not available. + + This is a no-op decorator that returns the original function. + It allows the code to continue working without pluggy, though + plugins will be disabled. + """ + if func is None: + return lambda f: f + return func + PLUGGY_AVAILABLE = False + logging.getLogger(__name__).warning("Pluggy not available, plugins will be disabled") + import traceback + logging.getLogger(__name__).debug(traceback.format_exc()) + +logger = logging.getLogger(__name__) + +class Plugin: + """Base class for Cthulhu plugins.""" + + def __init__(self): + """Initialize the plugin with default attributes.""" + self.app = None + self.plugin_info = None + self.module_name = '' + self.name = '' + self.version = '' + self.description = '' + self._bindings = None + self._gestureBindings = {} + + def set_app(self, app): + """Set the application reference.""" + self.app = app + + def set_plugin_info(self, plugin_info): + """Set plugin information and extract relevant attributes.""" + self.plugin_info = plugin_info + if plugin_info: + self.module_name = getattr(plugin_info, 'module_name', '') + self.name = getattr(plugin_info, 'name', '') + self.version = getattr(plugin_info, 'version', '') + self.description = getattr(plugin_info, 'description', '') + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin. Override this in subclasses.""" + if plugin is not None and plugin is not self: + return + logger.info(f"Activating plugin: {self.name}") + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin. Override this in subclasses.""" + if plugin is not None and plugin is not self: + return + logger.info(f"Deactivating plugin: {self.name}") + + def get_bindings(self): + """Get keybindings for this plugin. Override in subclasses.""" + return self._bindings + + def registerGestureByString(self, function, name, gestureString, learnModeEnabled=True): + """Register a gesture by string.""" + if self.app: + api_helper = self.app.getAPIHelper() + if api_helper: + binding = api_helper.registerGestureByString( + function, + name, + gestureString, + 'default', + 'cthulhu', + learnModeEnabled, + contextName=self.module_name + ) + + # Also store the binding locally so get_bindings() can use it + if binding: + if not self._bindings: + from . import keybindings + self._bindings = keybindings.KeyBindings() + self._bindings.add(binding) + + return binding + return None diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin_system_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin_system_manager.py new file mode 100644 index 0000000..e0feb65 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugin_system_manager.py @@ -0,0 +1,671 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 Stormux +# +# 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. + +"""Plugin System Manager for Cthulhu using pluggy.""" + +import os +import inspect +import importlib.util +import logging +from enum import IntEnum + +# Import pluggy if available +try: + import pluggy + PLUGGY_AVAILABLE = True +except ImportError: + PLUGGY_AVAILABLE = False + logging.getLogger(__name__).info("Pluggy not available, plugins will be disabled") + +# Set to True for more detailed plugin loading debug info +PLUGIN_DEBUG = True + +logger = logging.getLogger(__name__) +if PLUGIN_DEBUG: + logger.setLevel(logging.DEBUG) + +class PluginType(IntEnum): + """Types of plugins we support.""" + SYSTEM = 1 + USER = 2 + + def get_root_dir(self): + """Returns the directory where this type of plugins can be found.""" + if self.value == PluginType.SYSTEM: + current_file = inspect.getfile(inspect.currentframe()) + current_dir = os.path.dirname(os.path.realpath(os.path.abspath(current_file))) + return os.path.join(current_dir, 'plugins') + elif self.value == PluginType.USER: + return os.path.expanduser('~/.local/share/cthulhu/plugins') + + +class PluginInfo: + """Information about a plugin.""" + + def __init__(self, name, module_name, module_dir, metadata=None): + self.name = name + self.module_name = module_name + self.module_dir = module_dir + self.metadata = metadata or {} + self.builtin = False + self.hidden = False + self.module = None + self.instance = None + self.loaded = False + + def get_module_name(self): + return self.module_name + + def get_name(self): + return self.metadata.get('name', self.name) + + def get_version(self): + return self.metadata.get('version', '0.0.0') + + def get_description(self): + return self.metadata.get('description', '') + + def get_module_dir(self): + return self.module_dir + + +class PluginSystemManager: + """Cthulhu Plugin Manager using pluggy.""" + + def __init__(self, app): + self.app = app + logger.info("Initializing PluginSystemManager") + + # Initialize plugin manager + if PLUGGY_AVAILABLE: + logger.info("Pluggy is available, setting up plugin manager") + self.plugin_manager = pluggy.PluginManager("cthulhu") + + # Define hook specifications + hook_spec = pluggy.HookspecMarker("cthulhu") + + class CthulhuHookSpecs: + @hook_spec + def activate(self, plugin=None): + """Called when the plugin is activated.""" + pass + + @hook_spec + def deactivate(self, plugin=None): + """Called when the plugin is deactivated.""" + pass + + logger.info("Adding hook specifications to plugin manager") + self.plugin_manager.add_hookspecs(CthulhuHookSpecs) + else: + logger.warning("Pluggy is not available, plugins will be disabled") + self.plugin_manager = None + + # Plugin storage + self._plugins = {} # module_name -> PluginInfo + self._active_plugins = [] + + # Create plugin directories + self._setup_plugin_dirs() + + # Log available plugins directory paths + logger.info(f"System plugins directory: {PluginType.SYSTEM.get_root_dir()}") + logger.info(f"User plugins directory: {PluginType.USER.get_root_dir()}") + + def register_plugin_global_keybindings(self, plugin): + """Register a plugin's keybindings with all scripts.""" + if not hasattr(plugin, 'get_bindings'): + return + + try: + bindings = plugin.get_bindings() + if not bindings or not bindings.keyBindings: + return + + logger.info(f"Registering global keybindings for plugin: {plugin.name}") + + # First register with the active script + from . import cthulhu_state + if cthulhu_state.activeScript: + active_script = cthulhu_state.activeScript + for binding in bindings.keyBindings: + active_script.getKeyBindings().add(binding) + from . import cthulhu + grab_ids = cthulhu.addKeyGrab(binding) + if grab_ids: + binding._grab_ids = grab_ids + + # Store these bindings for future script changes + plugin_name = plugin.name or plugin.module_name + if not hasattr(self, '_plugin_global_bindings'): + self._plugin_global_bindings = {} + self._plugin_global_bindings[plugin_name] = bindings + + # Connect to script changes to ensure bindings work with all scripts + if not hasattr(self, '_connected_to_script_changes'): + signal_manager = self.app.getSignalManager() + if signal_manager: + signal_manager.connectSignal('load-setting-completed', self._on_settings_changed, None) + self._connected_to_script_changes = True + except Exception as e: + logger.error(f"Error registering global keybindings for plugin {plugin.name}: {e}") + import traceback + logger.error(traceback.format_exc()) + + def refresh_active_script_keybindings(self): + """Force active script to refresh its keybindings to include plugin bindings.""" + from . import cthulhu_state + if cthulhu_state.activeScript: + active_script = cthulhu_state.activeScript + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f"=== refresh_active_script_keybindings() CALLED ===\n") + f.write(f"Active script: {active_script.name}\n") + + # Force the script to recreate its keybindings to include plugin bindings + old_keybindings = active_script.keyBindings + active_script.keyBindings = active_script.getKeyBindings() + + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f"Keybindings refreshed: old={len(old_keybindings.keyBindings) if old_keybindings else 0}, new={len(active_script.keyBindings.keyBindings)}\n") + + def register_plugin_keybindings_with_active_script(self): + """Register all plugin keybindings with the active script.""" + + logger.info("=== register_plugin_keybindings_with_active_script() CALLED ===") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write("=== register_plugin_keybindings_with_active_script() CALLED ===\n") + + if not PLUGGY_AVAILABLE: + logger.warning("PLUGGY not available") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write("ERROR: PLUGGY not available\n") + return + + from . import cthulhu_state + if not cthulhu_state.activeScript: + logger.warning("No active script available to register plugin keybindings") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write("ERROR: No active script available\n") + return + + active_script = cthulhu_state.activeScript + logger.info(f"Registering plugin keybindings with active script: {active_script}") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f"Active script: {active_script}\n") + + # First, register keybindings from APIHelper's stored bindings + # This is where plugin keybindings actually get stored + from . import cthulhu + api_helper = cthulhu.cthulhuApp.getAPIHelper() + if api_helper and hasattr(api_helper, '_gestureBindings'): + logger.info("=== FOUND APIHelper with _gestureBindings ===") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write("=== Registering stored gesture bindings from APIHelper ===\n") + f.write(f"Total contexts: {len(api_helper._gestureBindings)}\n") + + for context_name, bindings_list in api_helper._gestureBindings.items(): + logger.info(f"Processing context '{context_name}' with {len(bindings_list)} bindings") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f"Context '{context_name}': {len(bindings_list)} bindings\n") + + for binding in bindings_list: + logger.info(f"Adding stored binding: {binding.keysymstring} with modifiers {binding.modifiers}") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f" Binding: {binding.keysymstring} modifiers={binding.modifiers} desc={binding.handler.description}\n") + + # Check if binding already exists to avoid duplicates + if not active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"): + active_script.getKeyBindings().add(binding) + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f" ADDED to active script!\n") + + # Force recalculation of keycode if it wasn't set when device was None + if not binding.keycode and binding.keysymstring: + from . import keybindings + binding.keycode = keybindings.getKeycode(binding.keysymstring) + # Register key grab at system level - this was missing! + grab_ids = cthulhu.addKeyGrab(binding) + if grab_ids: + binding._grab_ids = grab_ids + else: + logger.warning(f"Failed to create key grab for {binding.keysymstring} - device may not be available") + else: + logger.info(f"Binding already exists: {binding.keysymstring}") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write(f" Already exists, skipped\n") + else: + logger.warning("=== NO APIHelper or no _gestureBindings found ===") + with open('/tmp/plugin_registration.log', 'a') as f: + f.write("ERROR: No APIHelper or no _gestureBindings found!\n") + if api_helper: + f.write(f"APIHelper exists but _gestureBindings: {hasattr(api_helper, '_gestureBindings')}\n") + else: + f.write("No APIHelper found!\n") + + # Also check the old method for any plugins that use get_bindings() + for pluginInfo in self._plugins.values(): + if not pluginInfo.loaded or not pluginInfo.instance: + continue + + plugin = pluginInfo.instance + if not hasattr(plugin, 'get_bindings') or not plugin.get_bindings(): + continue + + logger.info(f"Registering keybindings for plugin: {plugin.name}") + bindings = plugin.get_bindings() + for binding in bindings.keyBindings: + logger.info(f"Adding binding: {binding.keysymstring} with modifiers {binding.modifiers}") + # Check if binding already exists to avoid duplicates + if not active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"): + active_script.getKeyBindings().add(binding) + # Force recalculation of keycode if it wasn't set when device was None + if not binding.keycode and binding.keysymstring: + from . import keybindings + binding.keycode = keybindings.getKeycode(binding.keysymstring) + # Register key grab at system level - this was missing! + grab_ids = cthulhu.addKeyGrab(binding) + if grab_ids: + binding._grab_ids = grab_ids + else: + logger.warning(f"Failed to create key grab for {binding.keysymstring} - device may not be available") + + def _on_settings_changed(self, app=None): + """Re-register all plugin keybindings when settings change.""" + if not hasattr(self, '_plugin_global_bindings'): + return + + from . import cthulhu_state + if not cthulhu_state.activeScript: + return + + active_script = cthulhu_state.activeScript + for plugin_name, bindings in self._plugin_global_bindings.items(): + logger.info(f"Re-registering keybindings for plugin: {plugin_name}") + for binding in bindings.keyBindings: + # Check if binding already exists + if active_script.getKeyBindings().hasKeyBinding(binding, "keysNoMask"): + continue + + active_script.getKeyBindings().add(binding) + from . import cthulhu + grab_ids = cthulhu.addKeyGrab(binding) + if grab_ids: + binding._grab_ids = grab_ids + + def _setup_plugin_dirs(self): + """Ensure plugin directories exist.""" + os.makedirs(PluginType.SYSTEM.get_root_dir(), exist_ok=True) + os.makedirs(PluginType.USER.get_root_dir(), exist_ok=True) + + @property + def plugins(self): + """Get all available plugins.""" + return list(self._plugins.values()) + + def getApp(self): + return self.app + + def rescanPlugins(self): + """Scan for plugins in the plugin directories.""" + old_plugins = self._plugins.copy() + self._plugins = {} + + # Scan system and user plugins + self._scan_plugins_in_directory(PluginType.SYSTEM.get_root_dir()) + self._scan_plugins_in_directory(PluginType.USER.get_root_dir()) + + # Preserve state for already loaded plugins + for name, old_info in old_plugins.items(): + if name in self._plugins and old_info.loaded: + self._plugins[name].loaded = True + self._plugins[name].instance = old_info.instance + self._plugins[name].module = old_info.module + + def _scan_plugins_in_directory(self, directory): + """Scan for plugins in a directory.""" + if not os.path.exists(directory) or not os.path.isdir(directory): + logger.warning(f"Plugin directory not found or not a directory: {directory}") + return + + logger.info(f"Scanning for plugins in directory: {directory}") + for item in os.listdir(directory): + plugin_dir = os.path.join(directory, item) + if not os.path.isdir(plugin_dir): + continue + + # Check for the traditional structure first (plugin.py & plugin.info) + plugin_file = os.path.join(plugin_dir, "plugin.py") + metadata_file = os.path.join(plugin_dir, "plugin.info") + + # Fall back to [PluginName].py if plugin.py doesn't exist + if not os.path.isfile(plugin_file): + alternative_plugin_file = os.path.join(plugin_dir, f"{item}.py") + if os.path.isfile(alternative_plugin_file): + plugin_file = alternative_plugin_file + logger.info(f"Using alternative plugin file: {alternative_plugin_file}") + + # Check if we have any valid plugin file + if os.path.isfile(plugin_file): + # Extract plugin info + module_name = os.path.basename(plugin_dir) + logger.info(f"Found plugin: {module_name} in {plugin_dir}") + metadata = self._load_plugin_metadata(metadata_file) + + plugin_info = PluginInfo( + metadata.get('name', module_name), + module_name, + plugin_dir, + metadata + ) + + # Check if it's a built-in or hidden plugin + plugin_info.builtin = metadata.get('builtin', 'false').lower() == 'true' + plugin_info.hidden = metadata.get('hidden', 'false').lower() == 'true' + + logger.info(f"Adding plugin to registry: {module_name}") + self._plugins[module_name] = plugin_info + else: + logger.warning(f"No plugin file found in directory: {plugin_dir}") + + def _load_plugin_metadata(self, metadata_file): + """Load plugin metadata from a file.""" + metadata = {} + + if os.path.isfile(metadata_file): + try: + with open(metadata_file, 'r') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): + continue + + if '=' in line: + key, value = line.split('=', 1) + metadata[key.strip()] = value.strip() + except Exception as e: + logger.error(f"Error loading plugin metadata: {e}") + + return metadata + + def getActivePlugins(self): + """Get the list of active plugin names.""" + return self._active_plugins + + def get_active_plugins(self): + """Get the list of active plugin instances.""" + active_instances = [] + for plugin_name in self._active_plugins: + if plugin_name in self._plugins: + plugin_info = self._plugins[plugin_name] + if plugin_info.loaded and plugin_info.instance: + active_instances.append(plugin_info.instance) + return active_instances + + def setActivePlugins(self, activePlugins): + """Set active plugins and sync their state.""" + logger.info(f"PLUGIN SYSTEM: setActivePlugins called with: {activePlugins}") + logger.info(f"Setting active plugins: {activePlugins}") + + # Make sure we have scanned for plugins first + if not self._plugins: + logger.info("No plugins found, rescanning...") + self.rescanPlugins() + + self._active_plugins = activePlugins + + # Log active vs available plugins + available_plugins = [p.get_module_name() for p in self.plugins] + logger.info(f"Available plugins: {available_plugins}") + logger.info(f"Active plugins: {self._active_plugins}") + + # Check specifically for DisplayVersion + if 'DisplayVersion' in self._active_plugins: + logger.info("DisplayVersion is in active plugins list!") + else: + logger.warning("DisplayVersion is NOT in active plugins list!") + + # Find missing plugins + missing_plugins = [p for p in self._active_plugins if p not in available_plugins] + if missing_plugins: + logger.warning(f"Active plugins not found: {missing_plugins}") + + self.syncAllPluginsActive() + logger.info("=== PluginSystemManager.setActivePlugins completed ===") + + def setPluginActive(self, pluginInfo, active): + """Set the active state of a plugin.""" + if pluginInfo.builtin: + active = True + + pluginName = pluginInfo.get_module_name() + + if active: + if pluginName not in self.getActivePlugins(): + if self.loadPlugin(pluginInfo): + self._active_plugins.append(pluginName) + else: + if pluginName in self.getActivePlugins(): + if self.unloadPlugin(pluginInfo): + self._active_plugins.remove(pluginName) + + def isPluginActive(self, pluginInfo): + """Check if a plugin is active.""" + module_name = pluginInfo.get_module_name() + + # Builtin plugins are always active + if pluginInfo.builtin: + logger.debug(f"Plugin {module_name} is builtin, active by default") + return True + + # If a plugin is already loaded, it's active + if pluginInfo.loaded: + logger.debug(f"Plugin {module_name} is already loaded, considered active") + return True + + # Check case-insensitive match in active plugins list + active_plugins = self.getActivePlugins() + + # Try exact match first + if module_name in active_plugins: + logger.debug(f"Plugin {module_name} found in active plugins list") + return True + + # Try case-insensitive match + module_name_lower = module_name.lower() + is_active = any(plugin.lower() == module_name_lower for plugin in active_plugins) + + if is_active: + logger.debug(f"Plugin {module_name} found in active plugins list (case-insensitive match)") + else: + logger.debug(f"Plugin {module_name} not found in active plugins list") + + return is_active + + def syncAllPluginsActive(self): + """Sync the active state of all plugins.""" + logger.info("Syncing active state of all plugins") + + # Log plugin status before syncing + if PLUGIN_DEBUG: + for pluginInfo in self.plugins: + is_active = self.isPluginActive(pluginInfo) + is_loaded = pluginInfo.loaded + logger.debug(f"Plugin {pluginInfo.get_module_name()}: active={is_active}, loaded={is_loaded}") + + # First unload inactive plugins + for pluginInfo in self.plugins: + if not self.isPluginActive(pluginInfo) and pluginInfo.loaded: + logger.info(f"Unloading inactive plugin: {pluginInfo.get_module_name()}") + self.unloadPlugin(pluginInfo) + + # Then load active plugins + for pluginInfo in self.plugins: + if self.isPluginActive(pluginInfo) and not pluginInfo.loaded: + logger.info(f"Loading active plugin: {pluginInfo.get_module_name()}") + result = self.loadPlugin(pluginInfo) + logger.info(f"Plugin {pluginInfo.get_module_name()} load result: {result}") + + # Log final plugin status + active_plugins = [p.get_module_name() for p in self.plugins if p.loaded] + logger.info(f"Active plugins after sync: {active_plugins}") + inactive_plugins = [p.get_module_name() for p in self.plugins if not p.loaded] + logger.info(f"Inactive plugins after sync: {inactive_plugins}") + + def loadPlugin(self, pluginInfo): + """Load a plugin.""" + # Skip if pluggy is not available + if not PLUGGY_AVAILABLE: + logger.info(f"Skipping plugin {pluginInfo.get_name()}: pluggy not available") + return False + + module_name = pluginInfo.get_module_name() + logger.info(f"=== PluginSystemManager.loadPlugin starting for: {module_name} ===") + + try: + # Already loaded? + if pluginInfo.loaded: + logger.info(f"Plugin {module_name} already loaded, skipping") + return True + + # Try to find the plugin file + module_name = pluginInfo.get_module_name() + plugin_dir = pluginInfo.get_module_dir() + + # Check for plugin.py first (standard format) + plugin_file = os.path.join(plugin_dir, "plugin.py") + + # Fall back to [PluginName].py if plugin.py doesn't exist + if not os.path.exists(plugin_file): + alternative_plugin_file = os.path.join(plugin_dir, f"{module_name}.py") + if os.path.exists(alternative_plugin_file): + plugin_file = alternative_plugin_file + logger.info(f"Using alternative plugin file: {alternative_plugin_file}") + + if not os.path.exists(plugin_file): + logger.error(f"Plugin file not found: {plugin_file}") + return False + + logger.info(f"Loading plugin from: {plugin_file}") + spec = importlib.util.spec_from_file_location(module_name, plugin_file) + if spec is None: + logger.error(f"Failed to create spec for plugin: {module_name}") + return False + + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + pluginInfo.module = module + + # Find Plugin class + plugin_class = None + for attr_name in dir(module): + attr = getattr(module, attr_name) + if (inspect.isclass(attr) and + attr.__module__ == module.__name__ and + hasattr(attr, 'activate')): + plugin_class = attr + logger.info(f"Found plugin class: {attr.__name__} in {module_name}") + break + + if not plugin_class: + logger.error(f"No plugin class found in {module_name}") + return False + + # Create and initialize plugin instance + logger.info(f"Creating instance of plugin class: {plugin_class.__name__}") + plugin_instance = plugin_class() + pluginInfo.instance = plugin_instance + + # Ensure plugins have a reference to the app + plugin_instance.app = self.getApp() + logger.info(f"Set app reference for plugin: {module_name}") + + if hasattr(plugin_instance, 'set_app'): + plugin_instance.set_app(self.getApp()) + logger.info(f"Called set_app() for plugin: {module_name}") + + if hasattr(plugin_instance, 'set_plugin_info'): + plugin_instance.set_plugin_info(pluginInfo) + logger.info(f"Called set_plugin_info() for plugin: {module_name}") + + # Register with pluggy and activate + if self.plugin_manager is None: + logger.error(f"Plugin manager is None when loading {module_name}") + return False + + logger.info(f"Registering plugin with pluggy: {module_name}") + self.plugin_manager.register(plugin_instance) + + try: + logger.info(f"Activating plugin: {module_name}") + self.plugin_manager.hook.activate(plugin=plugin_instance) + except Exception as e: + logger.error(f"Error activating plugin {module_name}: {e}") + import traceback + logger.error(traceback.format_exc()) + return False + + pluginInfo.loaded = True + logger.info(f"Successfully loaded plugin: {module_name}") + + # Register any global keybindings from the plugin + self.register_plugin_global_keybindings(pluginInfo.instance) + + return True + + except Exception as e: + logger.error(f"Failed to load plugin {module_name}: {e}") + import traceback + logger.error(traceback.format_exc()) + return False + + def unloadPlugin(self, pluginInfo): + """Unload a plugin.""" + # Skip if pluggy is not available + if not PLUGGY_AVAILABLE: + return False + + if pluginInfo.builtin: + return False + + module_name = pluginInfo.get_module_name() + + try: + # Not loaded? + if not pluginInfo.loaded: + return True + + # Deactivate plugin + plugin_instance = pluginInfo.instance + if plugin_instance: + try: + self.plugin_manager.hook.deactivate(plugin=plugin_instance) + except Exception as e: + logger.error(f"Error deactivating plugin {module_name}: {e}") + + # Unregister from pluggy + self.plugin_manager.unregister(plugin_instance) + + # Clean up + pluginInfo.instance = None + pluginInfo.loaded = False + + logger.info(f"Unloaded plugin: {module_name}") + return True + + except Exception as e: + logger.error(f"Failed to unload plugin {module_name}: {e}") + return False + + def unloadAllPlugins(self, ForceAllPlugins=False): + """Unload all plugins.""" + if not PLUGGY_AVAILABLE: + return + + for pluginInfo in self.plugins: + if ForceAllPlugins or pluginInfo.loaded: + self.unloadPlugin(pluginInfo) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/__init__.py new file mode 100644 index 0000000..34733fd --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/__init__.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""AI Assistant plugin package.""" + +from .plugin import AIAssistant \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/ai_providers.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/ai_providers.py new file mode 100644 index 0000000..04149f6 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/ai_providers.py @@ -0,0 +1,426 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""AI providers for the AI Assistant plugin.""" + +import logging +import json +import requests +from abc import ABC, abstractmethod + +logger = logging.getLogger(__name__) + +class AIProvider(ABC): + """Abstract base class for AI providers.""" + + def __init__(self, api_key=None, model=None, **kwargs): + self.api_key = api_key + self.model = model + self.kwargs = kwargs + + @abstractmethod + def describe_screen(self, screenshot_data, accessibility_data): + """Generate a description of the current screen.""" + pass + + @abstractmethod + def answer_question(self, question, screenshot_data, accessibility_data): + """Answer a question about the current screen/focus.""" + pass + + @abstractmethod + def suggest_actions(self, request, screenshot_data, accessibility_data): + """Suggest actions to accomplish a user's request.""" + pass + + def _prepare_system_prompt(self, task_type): + """Prepare system prompt based on task type.""" + base_prompt = """You are an AI assistant helping a screen reader user navigate and interact with computer applications. You have access to: + +1. A screenshot of the current screen +2. Detailed accessibility tree information about UI elements +3. Information about the currently focused element + +The user is using the Cthulhu screen reader, so they cannot see the screen visually. Your responses should be clear, concise, and focused on accessibility. + +""" + + if task_type == "describe": + return base_prompt + """Your task: Provide a clear, structured description of what's on the screen. Focus on: +- Main UI elements and their layout +- Current focus location +- Available actions and navigation options +- Any important visual information not captured in accessibility data + +Keep descriptions concise but informative.""" + + elif task_type == "question": + return base_prompt + """Your task: Answer the user's question about the current screen or focused element. Use both the screenshot and accessibility data to provide accurate, helpful information. + +Be specific and actionable in your responses.""" + + elif task_type == "action": + return base_prompt + """Your task: I WILL EXECUTE THE ACTION IMMEDIATELY - provide the structured response format only. + +🚨 CRITICAL RULES: +- I am the action execution system - I WILL perform the action, not give instructions +- NEVER provide programming code, implementation steps, or "how to" instructions +- NEVER mention ASCII codes, KEY_DOWN events, or technical implementation details +- Always use ACTION TYPE: COPY, TYPE, CLICK, SCROLL, or NAVIGATE +- Be direct about what I will do + +STRICT ACTION TYPE MAPPING: +- "find [element] and enter [text]" → ACTION TYPE: TYPE (I will locate element and type text) +- "type [text]" → ACTION TYPE: TYPE (I will type the specified text) +- "copy [text] to clipboard" → ACTION TYPE: COPY (I will copy to clipboard) +- "click [element]" → ACTION TYPE: CLICK (I will click the element) + +MANDATORY RESPONSE FORMAT: + +**ACTION ANALYSIS**: I will [specific action] +**TARGET ELEMENT**: [element description] +**ACTION TYPE**: [TYPE/COPY/CLICK/SCROLL/NAVIGATE] +**SAFETY CHECK**: [any concerns] +**STEP-BY-STEP**: What I will execute (NO CODE, NO IMPLEMENTATION DETAILS) + +Example for "find edit box and enter text": +**ACTION ANALYSIS**: I will locate the edit box and type the specified text into it +**TARGET ELEMENT**: Text input field ("What's on your mind?" edit box) +**ACTION TYPE**: TYPE +**SAFETY CHECK**: This will input text into the focused text field +**STEP-BY-STEP**: +1. Locate the edit box in the interface +2. Focus on the edit box +3. Type the requested text into the field + +🚨 NEVER GIVE PROGRAMMING CODE OR TECHNICAL INSTRUCTIONS""" + + return base_prompt + + +class ClaudeProvider(AIProvider): + """Claude AI provider using Anthropic's API.""" + + def __init__(self, api_key, model="claude-3-5-sonnet-20241022", **kwargs): + super().__init__(api_key, model, **kwargs) + self.base_url = "https://api.anthropic.com/v1/messages" + self.headers = { + "Content-Type": "application/json", + "X-API-Key": self.api_key, + "anthropic-version": "2023-06-01" + } + + def describe_screen(self, screenshot_data, accessibility_data): + """Generate a description using Claude.""" + try: + prompt = self._build_prompt("describe", None, accessibility_data) + return self._make_request(prompt, screenshot_data) + except Exception as e: + logger.error(f"Claude describe error: {e}") + return f"Error getting screen description: {e}" + + def answer_question(self, question, screenshot_data, accessibility_data): + """Answer a question using Claude.""" + try: + prompt = self._build_prompt("question", question, accessibility_data) + return self._make_request(prompt, screenshot_data) + except Exception as e: + logger.error(f"Claude question error: {e}") + return f"Error answering question: {e}" + + def suggest_actions(self, request, screenshot_data, accessibility_data): + """Suggest actions using Claude.""" + try: + prompt = self._build_prompt("action", request, accessibility_data) + return self._make_request(prompt, screenshot_data) + except Exception as e: + logger.error(f"Claude action error: {e}") + return f"Error suggesting actions: {e}" + + def _build_prompt(self, task_type, user_input, accessibility_data): + """Build the complete prompt for Claude.""" + prompt = f"Current accessibility information:\n```json\n{json.dumps(accessibility_data, indent=2)}\n```\n\n" + + if task_type == "describe": + prompt += "Please describe what's on this screen." + elif task_type == "question": + prompt += f"User question: {user_input}" + elif task_type == "action": + prompt += f"User wants to: {user_input}\n\nPlease suggest specific steps to accomplish this." + + return prompt + + def _make_request(self, prompt, screenshot_data): + """Make request to Claude API.""" + try: + # Prepare the message content + content = [ + { + "type": "text", + "text": prompt + } + ] + + # Add screenshot if available + if screenshot_data: + content.append({ + "type": "image", + "source": { + "type": "base64", + "media_type": f"image/{screenshot_data['format']}", + "data": screenshot_data['data'] + } + }) + + payload = { + "model": self.model, + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": content + } + ], + "system": self._prepare_system_prompt("describe") # Will be made dynamic later + } + + response = requests.post( + self.base_url, + headers=self.headers, + json=payload, + timeout=30 + ) + + if response.status_code == 200: + result = response.json() + return result['content'][0]['text'] + else: + error_msg = f"Claude API error {response.status_code}: {response.text}" + logger.error(error_msg) + return error_msg + + except requests.RequestException as e: + error_msg = f"Network error contacting Claude: {e}" + logger.error(error_msg) + return error_msg + except Exception as e: + error_msg = f"Unexpected error with Claude API: {e}" + logger.error(error_msg) + return error_msg + + +class ClaudeCodeProvider(AIProvider): + """Claude Code CLI provider - uses installed Claude Code application.""" + + def __init__(self, **kwargs): + super().__init__(**kwargs) + # No API key needed - uses Claude Code CLI directly + + def describe_screen(self, screenshot_data, accessibility_data): + """Generate a description using Claude Code CLI.""" + try: + prompt = self._build_prompt("describe", None, accessibility_data) + return self._call_claude_code(prompt) + except Exception as e: + logger.error(f"Claude Code describe error: {e}") + return f"Error getting screen description: {e}" + + def answer_question(self, question, screenshot_data, accessibility_data): + """Answer a question using Claude Code CLI.""" + try: + prompt = self._build_prompt("question", question, accessibility_data) + return self._call_claude_code(prompt) + except Exception as e: + logger.error(f"Claude Code question error: {e}") + return f"Error answering question: {e}" + + def suggest_actions(self, request, screenshot_data, accessibility_data): + """Suggest actions using Claude Code CLI.""" + try: + prompt = self._build_prompt("action", request, accessibility_data) + return self._call_claude_code(prompt) + except Exception as e: + logger.error(f"Claude Code action error: {e}") + return f"Error suggesting actions: {e}" + + def _build_prompt(self, task_type, user_input, accessibility_data): + """Build the complete prompt for Claude Code.""" + import json + + system_prompt = self._get_system_prompt(task_type) + + prompt = f"{system_prompt}\n\nCurrent accessibility information:\n```json\n{json.dumps(accessibility_data, indent=2)}\n```\n\n" + + if task_type == "describe": + prompt += "Please describe what's on this screen." + elif task_type == "question": + prompt += f"User question: {user_input}" + elif task_type == "action": + prompt += f"User wants to: {user_input}\n\nProvide the action analysis in the required format." + + return prompt + + def _call_claude_code(self, prompt): + """Call Claude Code CLI with the prompt.""" + import subprocess + + try: + # Call Claude Code CLI with the prompt directly + result = subprocess.run( + ['claude', '--print', '--output-format', 'text', prompt], + capture_output=True, + text=True, + timeout=60 + ) + + if result.returncode == 0: + return result.stdout.strip() + else: + error_msg = f"Claude Code CLI error: {result.stderr}" + logger.error(error_msg) + return error_msg + + except subprocess.TimeoutExpired: + error_msg = "Claude Code CLI timed out" + logger.error(error_msg) + return error_msg + except Exception as e: + error_msg = f"Error calling Claude Code CLI: {e}" + logger.error(error_msg) + return error_msg + + def _get_system_prompt(self, task_type): + """Get system prompt for Claude Code.""" + base_prompt = """You are Claude Code helping a screen reader user navigate and interact with computer applications. You have expert understanding of terminal commands, programming, and accessibility. + +The user is using the Cthulhu screen reader and cannot see the screen visually. Provide expert technical assistance. + +""" + + if task_type == "action": + return base_prompt + """CRITICAL: I WILL EXECUTE THE ACTION IMMEDIATELY. + +🚨 EXPERT COMMAND UNDERSTANDING: +- "type echo 'hello world'" → Extract exactly: echo 'hello world' +- "run ls -la" → Extract exactly: ls -la +- "execute ./configure --prefix=/usr" → Extract exactly: ./configure --prefix=/usr + +MANDATORY FORMAT: +**ACTION ANALYSIS**: I will [specific action] +**TARGET ELEMENT**: [element description] +**ACTION TYPE**: [TYPE/COPY/CLICK/SCROLL/NAVIGATE] +**SAFETY CHECK**: [assessment] +**STEP-BY-STEP**: What I will execute""" + + elif task_type == "describe": + return base_prompt + "Provide technical descriptions focusing on development tools, terminals, and accessibility elements." + + elif task_type == "question": + return base_prompt + "Answer with expert technical knowledge about programming, terminals, and system operations." + + return base_prompt + + +class OllamaProvider(AIProvider): + """Ollama local AI provider.""" + + def __init__(self, model="llama3.2-vision", base_url="http://localhost:11434", **kwargs): + super().__init__(model=model, **kwargs) + self.base_url = base_url + + def describe_screen(self, screenshot_data, accessibility_data): + """Generate a description using Ollama.""" + try: + prompt = self._build_prompt("describe", None, accessibility_data) + return self._make_request(prompt, screenshot_data) + except Exception as e: + logger.error(f"Ollama describe error: {e}") + return f"Error getting screen description: {e}" + + def answer_question(self, question, screenshot_data, accessibility_data): + """Answer a question using Ollama.""" + try: + prompt = self._build_prompt("question", question, accessibility_data) + return self._make_request(prompt, screenshot_data) + except Exception as e: + logger.error(f"Ollama question error: {e}") + return f"Error answering question: {e}" + + def suggest_actions(self, request, screenshot_data, accessibility_data): + """Suggest actions using Ollama.""" + try: + prompt = self._build_prompt("action", request, accessibility_data) + return self._make_request(prompt, screenshot_data) + except Exception as e: + logger.error(f"Ollama action error: {e}") + return f"Error suggesting actions: {e}" + + def _build_prompt(self, task_type, user_input, accessibility_data): + """Build the complete prompt for Ollama.""" + system_prompt = self._prepare_system_prompt(task_type) + + prompt = f"{system_prompt}\n\nCurrent accessibility information:\n```json\n{json.dumps(accessibility_data, indent=2)}\n```\n\n" + + if task_type == "describe": + prompt += "Please describe what's on this screen." + elif task_type == "question": + prompt += f"User question: {user_input}" + elif task_type == "action": + prompt += f"User wants to: {user_input}\n\nPlease suggest specific steps to accomplish this." + + return prompt + + def _make_request(self, prompt, screenshot_data): + """Make request to Ollama API.""" + try: + # For Ollama, we'll use the generate endpoint + payload = { + "model": self.model, + "prompt": prompt, + "stream": False + } + + # Note: Ollama vision support varies by model + # For now, we'll send text-only requests + # TODO: Add image support when Ollama vision models are more stable + + response = requests.post( + f"{self.base_url}/api/generate", + json=payload, + timeout=60 # Ollama can be slower + ) + + if response.status_code == 200: + result = response.json() + return result.get('response', 'No response from Ollama') + else: + error_msg = f"Ollama API error {response.status_code}: {response.text}" + logger.error(error_msg) + return error_msg + + except requests.RequestException as e: + error_msg = f"Network error contacting Ollama: {e}" + logger.error(error_msg) + return error_msg + except Exception as e: + error_msg = f"Unexpected error with Ollama API: {e}" + logger.error(error_msg) + return error_msg + + +def create_provider(provider_type, **kwargs): + """Factory function to create AI providers.""" + if provider_type == "claude": + return ClaudeProvider(**kwargs) + elif provider_type == "claude_code": + return ClaudeCodeProvider(**kwargs) + elif provider_type == "ollama": + return OllamaProvider(**kwargs) + else: + raise ValueError(f"Unknown provider type: {provider_type}") \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.info new file mode 100644 index 0000000..f9c5206 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.info @@ -0,0 +1,7 @@ +[Plugin] +Name = AI Assistant +Module = AIAssistant +Description = AI-powered accessibility assistant for analyzing screens and taking actions +Authors = Stormux +Version = 1.0.0 +Category = Accessibility \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.py new file mode 100644 index 0000000..d6e046f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/AIAssistant/plugin.py @@ -0,0 +1,1832 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""AI Assistant plugin for Cthulhu screen reader.""" + +import logging +import os +import json +import base64 +from io import BytesIO + +import gi +gi.require_version('Gdk', '3.0') +gi.require_version('GdkPixbuf', '2.0') +gi.require_version('Atspi', '2.0') +gi.require_version('Gtk', '3.0') +from gi.repository import Gdk, GdkPixbuf, Atspi, Gtk + +from cthulhu.plugin import Plugin, cthulhu_hookimpl +from cthulhu import settings +from cthulhu import settings_manager +from cthulhu import cthulhu_state +from cthulhu import ax_object +from cthulhu import ax_utilities +from cthulhu.ax_utilities_state import AXUtilitiesState +from cthulhu.plugins.AIAssistant.ai_providers import create_provider + +logger = logging.getLogger(__name__) + +class AIAssistant(Plugin): + """AI-powered accessibility assistant plugin. + + Provides AI-enhanced accessibility features including: + - Screen analysis using screenshots and AT-SPI data + - Natural language queries about UI elements + - Safe action assistance with user confirmation + - Multi-provider AI support (Claude, ChatGPT, Gemini, Ollama) + """ + + def __init__(self, *args, **kwargs): + """Initialize the AI Assistant plugin.""" + super().__init__(*args, **kwargs) + + # Use print to ensure we see this message + print("DEBUG: AI ASSISTANT __init__ called") + logger.info("AI ASSISTANT: Plugin __init__ starting") + logger.info("AI ASSISTANT: Plugin initialized successfully") + + # Menu and keybinding storage + self._kb_binding_menu = None + self._menu_gui = None + + # AI provider and settings + self._provider_type = None + self._ai_provider = None + self._api_key = None + self._ollama_model = None + self._ollama_endpoint = None + self._settings_manager = settings_manager.getManager() + + # Plugin enabled state + self._enabled = False + + # Pre-captured screen data (to avoid capturing dialog itself) + self._current_screen_data = None + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the AI Assistant plugin.""" + if plugin is not None and plugin is not self: + return + + # Prevent multiple activations + if self._enabled: + logger.info("AI ASSISTANT: Already activated, skipping") + print("DEBUG: AI ASSISTANT already activated, skipping") + return + + try: + logger.info("AI ASSISTANT: === Plugin activation starting ===") + print("DEBUG: AI ASSISTANT activation starting") + + # Check if AI Assistant is enabled in settings + enabled = self._settings_manager.getSetting('aiAssistantEnabled') + logger.info(f"AI ASSISTANT: Enabled setting: {enabled}") + print(f"DEBUG: AI ASSISTANT enabled setting: {enabled}") + if not enabled: + logger.info("AI Assistant is disabled in settings, skipping activation") + print("DEBUG: AI Assistant disabled, skipping activation") + return + + # Load AI settings + self._load_ai_settings() + print(f"DEBUG: AI settings loaded - provider: {self._provider_type}") + + # Check if we have valid configuration + config_valid = self._validate_configuration() + logger.info(f"AI Assistant configuration valid: {config_valid}") + print(f"DEBUG: AI Assistant configuration valid: {config_valid}") + if not config_valid: + logger.warning("AI Assistant configuration invalid, skipping activation") + print("DEBUG: AI Assistant configuration invalid, skipping activation") + return + + # Initialize AI provider + self._initialize_ai_provider() + print("DEBUG: AI provider initialized") + + # Register keybindings only if configuration is valid + self._register_keybindings() + print("DEBUG: AI keybindings registered") + + self._enabled = True + logger.info("AI Assistant plugin activated successfully") + print("DEBUG: AI Assistant plugin activated successfully") + + except Exception as e: + logger.error(f"Error activating AI Assistant plugin: {e}") + print(f"DEBUG: Error activating AI Assistant plugin: {e}") + import traceback + logger.error(traceback.format_exc()) + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the AI Assistant plugin.""" + if plugin is not None and plugin is not self: + return + + logger.info("Deactivating AI Assistant plugin") + + # Unregister keybindings + self._unregister_keybindings() + + self._enabled = False + + def _load_ai_settings(self): + """Load AI Assistant settings from Cthulhu configuration.""" + try: + # Get provider + provider = self._settings_manager.getSetting('aiProvider') + self._provider_type = provider or settings.AI_PROVIDER_CLAUDE + + # Load API key from file + api_key_file = self._settings_manager.getSetting('aiApiKeyFile') + if api_key_file and os.path.isfile(api_key_file): + with open(api_key_file, 'r') as f: + self._api_key = f.read().strip() + else: + self._api_key = None + + # Load Ollama model and endpoint + self._ollama_model = self._settings_manager.getSetting('aiOllamaModel') + if not self._ollama_model: + self._ollama_model = settings.aiOllamaModel + + self._ollama_endpoint = self._settings_manager.getSetting('aiOllamaEndpoint') + if not self._ollama_endpoint: + self._ollama_endpoint = settings.aiOllamaEndpoint + + logger.info(f"AI settings loaded: provider={self._provider_type}, " + f"api_key_configured={bool(self._api_key)}, " + f"ollama_model={self._ollama_model}, " + f"ollama_endpoint={self._ollama_endpoint}") + + except Exception as e: + logger.error(f"Error loading AI settings: {e}") + + def _validate_configuration(self): + """Validate AI Assistant configuration.""" + logger.info(f"Validating AI configuration - provider_type: {self._provider_type}") + if not self._provider_type: + logger.warning("No AI provider configured") + return False + + # Providers that don't need API keys + if self._provider_type == settings.AI_PROVIDER_OLLAMA: + logger.info("Checking Ollama availability") + return self._check_ollama_availability() + elif self._provider_type == settings.AI_PROVIDER_CLAUDE_CODE: + logger.info("Checking Claude Code availability") + result = self._check_claude_code_availability() + logger.info(f"Claude Code availability check result: {result}") + return result + + # Other providers need API keys + logger.info(f"Checking API key for provider {self._provider_type}") + if not self._api_key: + logger.warning(f"No API key configured for provider {self._provider_type}") + return False + + logger.info("Configuration validation passed") + return True + + def _check_ollama_availability(self): + """Check if Ollama is available and has vision models.""" + try: + import requests + # Check if Ollama is running at the configured endpoint + endpoint_url = f"{self._ollama_endpoint}/api/version" + response = requests.get(endpoint_url, timeout=5) + if response.status_code == 200: + logger.info(f"Ollama service is available at {self._ollama_endpoint}") + return True + else: + logger.warning(f"Ollama service not responding at {self._ollama_endpoint}") + return False + except Exception as e: + logger.warning(f"Ollama not available at {self._ollama_endpoint}: {e}") + return False + + def _check_claude_code_availability(self): + """Check if Claude Code CLI is available.""" + try: + import subprocess + import shutil + + # First check if claude command exists in PATH + if not shutil.which('claude'): + logger.warning("Claude Code CLI not found in PATH") + return False + + # Quick test to see if it responds + result = subprocess.run(['claude', '--version'], + capture_output=True, text=True, timeout=5) + if result.returncode == 0: + logger.info("Claude Code CLI is available") + return True + else: + logger.warning(f"Claude Code CLI not responding: {result.stderr}") + return False + except subprocess.TimeoutExpired: + logger.warning("Claude Code CLI timeout") + return False + except Exception as e: + logger.warning(f"Claude Code CLI not available: {e}") + return False + + def _initialize_ai_provider(self): + """Initialize the AI provider based on settings.""" + try: + if self._provider_type == settings.AI_PROVIDER_CLAUDE: + self._ai_provider = create_provider("claude", api_key=self._api_key) + elif self._provider_type == settings.AI_PROVIDER_CLAUDE_CODE: + self._ai_provider = create_provider("claude_code") + elif self._provider_type == settings.AI_PROVIDER_OLLAMA: + self._ai_provider = create_provider("ollama", model=self._ollama_model, base_url=self._ollama_endpoint) + else: + logger.error(f"Unsupported provider type: {self._provider_type}") + return False + + logger.info(f"AI provider initialized: {self._provider_type}") + return True + + except Exception as e: + logger.error(f"Error initializing AI provider: {e}") + return False + + def _register_keybindings(self): + """Register AI Assistant menu keybinding.""" + try: + # Single keybinding to show AI Assistant menu + self._kb_binding_menu = self.registerGestureByString( + self._show_ai_menu, + "Show AI Assistant menu", + 'kb:cthulhu+shift+control+a' + ) + + logger.info("AI Assistant menu keybinding registered") + print(f"DEBUG: AI Assistant menu keybinding registered: {self._kb_binding_menu}") + + except Exception as e: + logger.error(f"Error registering AI menu keybinding: {e}") + + def _unregister_keybindings(self): + """Unregister AI Assistant keybindings.""" + # Keybindings are automatically cleaned up when plugin deactivates + self._kb_binding_menu = None + self._menu_gui = None + + def _show_ai_menu(self, script=None, inputEvent=None): + """Show the AI Assistant menu.""" + try: + logger.info("AI ASSISTANT: _show_ai_menu called!") + print("DEBUG: AI ASSISTANT _show_ai_menu called!") + + # IMPORTANT: Capture screen data BEFORE showing menu + # This ensures we get the actual screen content, not the menu itself + self._pre_menu_screen_data = self._collect_ai_data() + logger.info("Pre-captured screen data for menu actions") + print("DEBUG: Pre-captured screen data for menu actions") + + # Now show the menu + self._menu_gui = AIAssistantMenu(self._handle_menu_selection) + self._menu_gui.show_gui() + print("DEBUG: AI menu GUI shown") + return True + except Exception as e: + logger.error(f"Error showing AI menu: {e}") + print(f"DEBUG: Error showing AI menu: {e}") + import traceback + traceback.print_exc() + return False + + def _handle_menu_selection(self, action_id): + """Handle AI Assistant menu selection.""" + try: + logger.info(f"AI menu selection: {action_id}") + + if action_id == "ask_question": + self._handle_ai_question_with_data(self._pre_menu_screen_data) + elif action_id == "describe_screen": + self._handle_ai_describe_with_data(self._pre_menu_screen_data) + elif action_id == "request_action": + self._handle_ai_activate_with_data(self._pre_menu_screen_data) + else: + logger.warning(f"Unknown AI menu action: {action_id}") + + except Exception as e: + logger.error(f"Error handling menu selection {action_id}: {e}") + + def _handle_ai_describe_with_data(self, data): + """Handle AI screen description request with pre-captured data.""" + try: + logger.info("AI screen description requested with pre-captured data") + + if not self._enabled: + self._present_message("AI Assistant is not enabled") + return True + + # Use AI to describe the current screen + if not self._ai_provider: + self._present_message("AI provider not available. Check configuration.") + return True + + provider_name = self._provider_type.replace('_', ' ').title() + self._present_message(f"AI Assistant ({provider_name}) analyzing screen...") + + # Use pre-captured data + if data: + try: + response = self._ai_provider.describe_screen( + data.get('screenshot'), + data.get('accessibility') + ) + self._show_description_dialog(response) + except Exception as e: + logger.error(f"Error getting AI screen description: {e}") + self._present_message(f"Error getting AI screen description: {e}") + else: + self._present_message("Could not collect screen data for analysis") + + return True + except Exception as e: + logger.error(f"Error in AI describe handler: {e}") + return False + + def _handle_ai_question_with_data(self, data): + """Handle AI question request with pre-captured data.""" + try: + logger.info("AI question requested with pre-captured data") + + if not self._enabled: + self._present_message("AI Assistant is not enabled") + return True + + if not self._ai_provider: + self._present_message("AI provider not available. Check configuration.") + return True + + # Store the pre-captured data for use by the question dialog + self._current_screen_data = data + + # Show question dialog + self._show_question_dialog() + return True + except Exception as e: + logger.error(f"Error in AI question handler: {e}") + return False + + def _handle_ai_activate_with_data(self, data): + """Handle AI action request with pre-captured data.""" + try: + logger.info("AI action requested with pre-captured data") + + if not self._enabled: + self._present_message("AI Assistant is not enabled") + return True + + if not self._ai_provider: + self._present_message("AI provider not available. Check configuration.") + return True + + # Store the pre-captured data for use by the action dialog + self._current_screen_data = data + + # Show action dialog + self._show_action_dialog() + return True + except Exception as e: + logger.error(f"Error in AI action handler: {e}") + return False + + def _handle_ai_activate(self, script=None, inputEvent=None): + """Handle main AI Assistant activation - now shows action dialog.""" + try: + logger.info("AI Assistant activation requested") + print("DEBUG: AI Assistant activation keybinding triggered!") + + if not self._enabled: + print("DEBUG: AI Assistant not enabled, presenting message") + self._present_message("AI Assistant is not enabled") + return True + + if not self._ai_provider: + self._present_message("AI provider not available. Check configuration.") + return True + + # NEW: Show action request dialog for Phase 5 + self._present_message("AI Assistant capturing screen data for action...") + self._current_screen_data = self._collect_ai_data() + + if not self._current_screen_data: + self._present_message("Could not collect screen data for action") + return True + + # Show action request dialog + self._show_action_dialog() + + return True + + except Exception as e: + logger.error(f"Error in AI activate handler: {e}") + return False + + def _handle_ai_question(self, script=None, inputEvent=None): + """Handle AI question request.""" + try: + logger.info("AI question requested") + + if not self._enabled: + self._present_message("AI Assistant is not enabled") + return True + + if not self._ai_provider: + self._present_message("AI provider not available. Check configuration.") + return True + + # IMPORTANT: Collect screen data BEFORE opening dialog + # This captures the actual window the user is asking about + self._present_message("AI Assistant capturing screen data...") + self._current_screen_data = self._collect_ai_data() + + if not self._current_screen_data: + self._present_message("Could not collect screen data for analysis") + return True + + # Now show question dialog + self._show_question_dialog() + + return True + + except Exception as e: + logger.error(f"Error in AI question handler: {e}") + return False + + def _handle_ai_describe(self, script=None, inputEvent=None): + """Handle AI screen description request.""" + try: + logger.info("AI screen description requested") + + if not self._enabled: + self._present_message("AI Assistant is not enabled") + return True + + # Use AI to describe the current screen + if not self._ai_provider: + self._present_message("AI provider not available. Check configuration.") + return True + + provider_name = self._provider_type.replace('_', ' ').title() + self._present_message(f"AI Assistant ({provider_name}) analyzing screen...") + + # Collect data and get AI description + data = self._collect_ai_data() + if data: + try: + response = self._ai_provider.describe_screen( + data.get('screenshot'), + data.get('accessibility') + ) + self._show_description_dialog(response) + except Exception as e: + logger.error(f"Error getting AI screen description: {e}") + self._present_message(f"Error getting AI screen description: {e}") + else: + self._present_message("Could not collect screen data for analysis") + + return True + + except Exception as e: + logger.error(f"Error in AI describe handler: {e}") + return False + + def _present_message(self, message): + """Present a message to the user via speech.""" + try: + if self.app: + state = self.app.getDynamicApiManager().getAPI('CthulhuState') + if state and state.activeScript: + state.activeScript.presentMessage(message, resetStyles=False) + else: + logger.warning("No active script available for message presentation") + else: + logger.warning("No app reference available for message presentation") + except Exception as e: + logger.error(f"Error presenting message: {e}") + + def _capture_screenshot(self): + """Capture a screenshot of the current display.""" + try: + # Get the default display and root window + display = Gdk.Display.get_default() + if not display: + logger.error("No display available for screenshot") + return None + + screen = display.get_default_screen() + root_window = screen.get_root_window() + + # Get screen dimensions + width = screen.get_width() + height = screen.get_height() + + # Capture the screenshot + pixbuf = Gdk.pixbuf_get_from_window(root_window, 0, 0, width, height) + + if not pixbuf: + logger.error("Failed to capture screenshot") + return None + + # Convert to base64 for AI transmission + success, buffer = pixbuf.save_to_bufferv("png", [], []) + if not success: + logger.error("Failed to save pixbuf to buffer") + return None + image_data = base64.b64encode(buffer).decode('utf-8') + + logger.info(f"Screenshot captured: {width}x{height}") + return { + 'format': 'png', + 'width': width, + 'height': height, + 'data': image_data + } + + except Exception as e: + logger.error(f"Error capturing screenshot: {e}") + return None + + def _get_accessibility_tree(self): + """Get accessibility tree information for the current focus.""" + try: + # Get the current focus object + focus_obj = cthulhu_state.locusOfFocus + if not focus_obj: + logger.warning("No focus object available") + return None + + # Collect accessibility information + tree_data = { + 'focus': self._serialize_ax_object(focus_obj), + 'context': [], + 'actionable_elements': [] # New: For action system + } + + # Get parent context (up to 3 levels) + parent = ax_object.AXObject.get_parent(focus_obj) + level = 0 + while parent and level < 3: + tree_data['context'].append(self._serialize_ax_object(parent)) + parent = ax_object.AXObject.get_parent(parent) + level += 1 + + # Get children of focus (if any) + child_count = ax_object.AXObject.get_child_count(focus_obj) + if child_count > 0: + children = [] + for i in range(min(child_count, 10)): # Limit to first 10 + child = ax_object.AXObject.get_child(focus_obj, i) + if child: + children.append(self._serialize_ax_object(child)) + if children: + tree_data['children'] = children + + # NEW: Collect actionable elements for AI actions + tree_data['actionable_elements'] = self._collect_actionable_elements() + + logger.info(f"Accessibility tree collected for {ax_object.AXObject.get_name(focus_obj) or 'unnamed object'}") + return tree_data + + except Exception as e: + logger.error(f"Error getting accessibility tree: {e}") + return None + + def _serialize_ax_object(self, obj, include_actions=False): + """Serialize an accessibility object to JSON-compatible format.""" + try: + if not obj: + return None + + data = { + 'name': ax_object.AXObject.get_name(obj) or '', + 'role': ax_object.AXObject.get_role_name(obj) or '', + 'description': ax_object.AXObject.get_description(obj) or '', + 'text': self._get_object_text(obj), + 'value': self._get_object_value(obj), + 'states': self._get_object_states(obj), + 'attributes': self._get_object_attributes(obj), + 'position': self._get_object_position(obj) + } + + # Include action information for actionable elements + if include_actions: + data['actions'] = self._get_object_actions(obj) + data['is_actionable'] = self._is_actionable_element(obj) + data['action_coordinates'] = self._get_action_coordinates(obj) + + return data + + except Exception as e: + logger.error(f"Error serializing accessibility object: {e}") + return None + + def _get_object_text(self, obj): + """Get text content from an accessibility object.""" + try: + # Use script utilities to get displayed text if available + if cthulhu_state.activeScript and hasattr(cthulhu_state.activeScript, 'utilities'): + try: + text = cthulhu_state.activeScript.utilities.displayedText(obj) + if text: + return text.strip() + except: + pass + + # Fallback: try direct AT-SPI text interface + try: + if ax_object.AXObject.supports_text(obj): + text_iface = obj.queryText() + if text_iface: + text = text_iface.getText(0, -1) + if text: + return text.strip() + except: + pass + + return "" + + except Exception as e: + logger.error(f"Error getting object text: {e}") + return "" + + def _get_object_value(self, obj): + """Get value from an accessibility object.""" + try: + if ax_object.AXObject.supports_value(obj): + try: + value_iface = obj.queryValue() + if value_iface: + return str(value_iface.currentValue) or "" + except: + pass + return "" + + except Exception as e: + logger.error(f"Error getting object value: {e}") + return "" + + def _get_object_states(self, obj): + """Get state information from an accessibility object.""" + try: + states = [] + if AXUtilitiesState.is_focused(obj): + states.append("focused") + if AXUtilitiesState.is_selected(obj): + states.append("selected") + if AXUtilitiesState.is_expanded(obj): + states.append("expanded") + if AXUtilitiesState.is_checked(obj): + states.append("checked") + if AXUtilitiesState.is_sensitive(obj): + states.append("sensitive") + if AXUtilitiesState.is_showing(obj): + states.append("showing") + if AXUtilitiesState.is_visible(obj): + states.append("visible") + + return states + + except Exception as e: + logger.error(f"Error getting object states: {e}") + return [] + + def _get_object_attributes(self, obj): + """Get attributes from an accessibility object.""" + try: + attrs = {} + + # Get object attributes from AT-SPI + try: + if hasattr(obj, 'get_attributes'): + obj_attrs = obj.get_attributes() + if obj_attrs: + attrs['object_attributes'] = dict(obj_attrs) + except: + pass + + return attrs + + except Exception as e: + logger.error(f"Error getting object attributes: {e}") + return {} + + def _get_object_position(self, obj): + """Get position and size information from an accessibility object.""" + try: + if hasattr(obj, 'queryComponent'): + component = obj.queryComponent() + if component: + extents = component.getExtents(Atspi.CoordType.SCREEN) + return { + 'x': extents.x, + 'y': extents.y, + 'width': extents.width, + 'height': extents.height + } + return None + + except Exception as e: + logger.error(f"Error getting object position: {e}") + return None + + def _collect_ai_data(self): + """Collect both screenshot and accessibility data for AI analysis.""" + try: + logger.info("Collecting AI data (screenshot + accessibility tree)") + + # Collect both types of data + screenshot = self._capture_screenshot() + accessibility_tree = self._get_accessibility_tree() + + data = { + 'timestamp': __import__('time').time(), + 'screenshot': screenshot, + 'accessibility': accessibility_tree + } + + # Add current application context + if cthulhu_state.activeScript: + app_name = getattr(cthulhu_state.activeScript, 'name', 'unknown') + data['application'] = app_name + + logger.info("AI data collection completed") + return data + + except Exception as e: + logger.error(f"Error collecting AI data: {e}") + return None + + def _show_question_dialog(self): + """Show a dialog for the user to enter their question.""" + try: + provider_name = self._provider_type.replace('_', ' ').title() + dialog = Gtk.Dialog( + title=f"AI Assistant Question ({provider_name})", + parent=None, + flags=Gtk.DialogFlags.MODAL, + buttons=( + Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OK, Gtk.ResponseType.OK + ) + ) + + dialog.set_default_size(500, 200) + + # Create the question entry + content_area = dialog.get_content_area() + + label = Gtk.Label(label="Enter your question about the current screen:") + label.set_halign(Gtk.Align.START) + content_area.pack_start(label, False, False, 10) + + entry = Gtk.Entry() + entry.set_placeholder_text("What would you like to know?") + entry.set_activates_default(True) + content_area.pack_start(entry, False, False, 10) + + dialog.set_default_response(Gtk.ResponseType.OK) + # Show all widgets including buttons + dialog.show_all() + + # Set focus to the entry + entry.grab_focus() + + response = dialog.run() + + if response == Gtk.ResponseType.OK: + question = entry.get_text().strip() + if question: + # Transform dialog to show processing and response + self._transform_dialog_for_response(dialog, question) + else: + dialog.destroy() + self._present_message("No question entered") + else: + dialog.destroy() + self._present_message("Question cancelled") + + except Exception as e: + logger.error(f"Error showing question dialog: {e}") + self._present_message(f"Error showing question dialog: {e}") + + def _transform_dialog_for_response(self, dialog, question): + """Transform the question dialog to show AI processing and response.""" + try: + # Clear existing content + content_area = dialog.get_content_area() + for child in content_area.get_children(): + content_area.remove(child) + + # Remove existing buttons + for child in dialog.get_action_area().get_children(): + dialog.get_action_area().remove(child) + + # Change title + provider_name = self._provider_type.replace('_', ' ').title() + dialog.set_title(f"AI Assistant Response ({provider_name})") + + # Show question and processing message + question_label = Gtk.Label() + question_label.set_markup(f"Question: {question}") + question_label.set_line_wrap(True) + question_label.set_halign(Gtk.Align.START) + content_area.pack_start(question_label, False, False, 10) + + # Create scrollable text view for response (same as description dialog) + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.set_shadow_type(Gtk.ShadowType.IN) + + self._response_text_view = Gtk.TextView() + self._response_text_view.set_editable(False) # Read-only + self._response_text_view.set_cursor_visible(True) # Allow cursor navigation for screen readers + self._response_text_view.set_wrap_mode(Gtk.WrapMode.WORD) + + # Set initial processing text + text_buffer = self._response_text_view.get_buffer() + text_buffer.set_text("Processing your question...") + + scrolled_window.add(self._response_text_view) + content_area.pack_start(scrolled_window, True, True, 10) + + # Add close button + close_button = dialog.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) + dialog.set_default_response(Gtk.ResponseType.CLOSE) + + # Resize for response content + dialog.set_default_size(600, 400) + dialog.show_all() + + # Focus the response text view so screen reader announces it + self._response_text_view.grab_focus() + + # Process question asynchronously + self._process_user_question_async(dialog, question) + + except Exception as e: + logger.error(f"Error transforming dialog: {e}") + dialog.destroy() + self._present_message(f"Error showing response: {e}") + + def _process_user_question_async(self, dialog, question): + """Process the user's question and update dialog with response.""" + try: + # Use the pre-captured screen data (captured before dialog opened) + data = self._current_screen_data + if data: + try: + response = self._ai_provider.answer_question( + question, + data.get('screenshot'), + data.get('accessibility') + ) + + # Update the response text view + text_buffer = self._response_text_view.get_buffer() + text_buffer.set_text(f"Response:\n{response}") + + # Also speak the response + self._present_message(response) + + # Set up dialog close handler + def on_response(dialog, response_id): + dialog.destroy() + + dialog.connect("response", on_response) + + except Exception as e: + logger.error(f"Error getting AI response: {e}") + text_buffer = self._response_text_view.get_buffer() + text_buffer.set_text(f"Error: {e}") + self._present_message(f"Error getting AI response: {e}") + else: + text_buffer = self._response_text_view.get_buffer() + text_buffer.set_text("Error: No screen data available") + self._present_message("No screen data available") + + except Exception as e: + logger.error(f"Error processing user question: {e}") + text_buffer = self._response_text_view.get_buffer() + text_buffer.set_text(f"Error: {e}") + self._present_message(f"Error processing question: {e}") + + # ============================================================================ + def _show_description_dialog(self, description): + """Show a read-only dialog with the screen description.""" + try: + provider_name = self._provider_type.replace('_', ' ').title() + dialog = Gtk.Dialog( + title=f"AI Screen Description ({provider_name})", + parent=None, + flags=Gtk.DialogFlags.MODAL, + buttons=(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) + ) + + dialog.set_default_size(600, 400) + + content_area = dialog.get_content_area() + + # Create scrollable text view + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.set_shadow_type(Gtk.ShadowType.IN) + + text_view = Gtk.TextView() + text_view.set_editable(False) # Read-only + text_view.set_cursor_visible(True) # Allow cursor navigation for screen readers + text_view.set_wrap_mode(Gtk.WrapMode.WORD) + + # Set the description text + text_buffer = text_view.get_buffer() + text_buffer.set_text(description) + + scrolled_window.add(text_view) + content_area.pack_start(scrolled_window, True, True, 10) + + dialog.set_default_response(Gtk.ResponseType.CLOSE) + dialog.show_all() + + # Focus the text view so screen reader reads the content + text_view.grab_focus() + + # Show dialog and wait for user to close + response = dialog.run() + dialog.destroy() + + except Exception as e: + logger.error(f"Error showing description dialog: {e}") + self._present_message(f"Error showing description: {e}") + + # NEW: Action System Methods for Phase 5 + # ============================================================================ + + def _collect_actionable_elements(self): + """Collect all actionable elements in the current window for AI analysis.""" + try: + logger.info("Collecting actionable elements for action system") + actionable_elements = [] + + # Get the current application's window + if not cthulhu_state.activeScript: + return actionable_elements + + # Start from the application root + app = cthulhu_state.activeScript.app + if not app: + return actionable_elements + + # Recursively find actionable elements + self._find_actionable_elements_recursive(app, actionable_elements, max_depth=5) + + logger.info(f"Found {len(actionable_elements)} actionable elements") + return actionable_elements + + except Exception as e: + logger.error(f"Error collecting actionable elements: {e}") + return [] + + def _find_actionable_elements_recursive(self, obj, actionable_elements, current_depth=0, max_depth=5): + """Recursively find actionable elements in the accessibility tree.""" + try: + if current_depth >= max_depth: + return + + if not obj: + return + + # Check if this element is actionable + if self._is_actionable_element(obj): + element_data = self._serialize_ax_object(obj, include_actions=True) + if element_data and element_data.get('is_actionable'): + actionable_elements.append(element_data) + + # Recurse through children + try: + child_count = ax_object.AXObject.get_child_count(obj) + for i in range(min(child_count, 20)): # Limit children to prevent overflow + child = ax_object.AXObject.get_child(obj, i) + if child: + self._find_actionable_elements_recursive( + child, actionable_elements, current_depth + 1, max_depth + ) + except: + pass + + except Exception as e: + logger.debug(f"Error in recursive element search: {e}") + + def _is_actionable_element(self, obj): + """Determine if an accessibility object is actionable for AI operations.""" + try: + if not obj: + return False + + # Get role and states + role = ax_object.AXObject.get_role_name(obj) + states = self._get_object_states(obj) + + # Define actionable roles + actionable_roles = { + 'push button', 'button', 'toggle button', 'radio button', 'check box', + 'menu item', 'list item', 'tree item', 'tab', 'link', 'entry', 'text', + 'password text', 'combo box', 'spin button', 'slider', 'scroll bar' + } + + # Check if role is actionable + if role and role.lower() in actionable_roles: + # Additional checks for enabled/visible states + if states: + state_names = [state.lower() for state in states] + # Element must be enabled and visible + if 'enabled' in state_names and 'visible' in state_names: + return True + + # Check for specific action interfaces + try: + actions = self._get_object_actions(obj) + if actions and len(actions) > 0: + return True + except: + pass + + return False + + except Exception as e: + logger.debug(f"Error checking if element is actionable: {e}") + return False + + def _get_object_actions(self, obj): + """Get available actions for an accessibility object.""" + try: + actions = [] + + # Check for AT-SPI action interface + try: + if hasattr(obj, 'queryAction'): + action_iface = obj.queryAction() + if action_iface: + action_count = action_iface.get_nActions() + for i in range(action_count): + action_name = action_iface.getName(i) + action_desc = action_iface.getDescription(i) + actions.append({ + 'name': action_name or '', + 'description': action_desc or '', + 'index': i + }) + except: + pass + + return actions + + except Exception as e: + logger.debug(f"Error getting object actions: {e}") + return [] + + def _get_action_coordinates(self, obj): + """Get coordinates for performing actions on an object.""" + try: + position = self._get_object_position(obj) + if position and 'x' in position and 'y' in position: + # Calculate center point for clicking + center_x = position['x'] + (position.get('width', 0) // 2) + center_y = position['y'] + (position.get('height', 0) // 2) + + return { + 'center_x': center_x, + 'center_y': center_y, + 'bounds': position + } + + return None + + except Exception as e: + logger.debug(f"Error getting action coordinates: {e}") + return None + + # ============================================================================ + # Action Dialog and Execution Methods + # ============================================================================ + + def _show_action_dialog(self): + """Show dialog for entering action requests.""" + try: + # Create dialog without parent first + dialog = Gtk.Dialog( + title="AI Assistant Actions", + flags=Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, + buttons=( + Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + "Analyze", Gtk.ResponseType.OK + ) + ) + + # Make dialog fully accessible + dialog.set_resizable(True) + dialog.set_modal(True) + dialog.set_type_hint(Gdk.WindowTypeHint.DIALOG) + + dialog.set_default_size(600, 300) + + content_area = dialog.get_content_area() + + # Instruction label + label = Gtk.Label() + label.set_markup("Tell the AI what you want to do:\n" + + "Examples: 'Click the Continue button', 'Enter storm into username field', " + + "'Copy this text to clipboard'") + label.set_line_wrap(True) + label.set_halign(Gtk.Align.START) + content_area.pack_start(label, False, False, 10) + + # Action entry + entry = Gtk.Entry() + entry.set_placeholder_text("What would you like me to do?") + entry.set_activates_default(True) + content_area.pack_start(entry, False, False, 10) + + dialog.set_default_response(Gtk.ResponseType.OK) + dialog.show_all() + + entry.grab_focus() + + response = dialog.run() + + if response == Gtk.ResponseType.OK: + action_request = entry.get_text().strip() + if action_request: + # Close this dialog and create a new confirmation dialog + dialog.destroy() + self._show_action_confirmation_dialog(action_request) + else: + dialog.destroy() + self._present_message("No action request entered") + else: + dialog.destroy() + self._present_message("Action request cancelled") + + except Exception as e: + logger.error(f"Error showing action dialog: {e}") + self._present_message(f"Error showing action dialog: {e}") + + def _show_action_confirmation_dialog(self, action_request): + """Show a fresh confirmation dialog for the action.""" + try: + # Create completely new dialog + dialog = Gtk.Dialog( + title="AI Assistant - Confirm Action", + flags=Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT + ) + + # Add buttons directly during dialog creation + cancel_button = dialog.add_button("Cancel", Gtk.ResponseType.CANCEL) + execute_button = dialog.add_button("Execute Action", Gtk.ResponseType.ACCEPT) + + # Configure dialog + dialog.set_default_size(600, 400) + dialog.set_resizable(True) + dialog.set_type_hint(Gdk.WindowTypeHint.DIALOG) + + # Configure buttons + execute_button.set_sensitive(False) # Disabled until analysis complete + execute_button.set_can_focus(True) + execute_button.set_can_default(True) + cancel_button.set_can_focus(True) + + dialog.set_default_response(Gtk.ResponseType.ACCEPT) + + content_area = dialog.get_content_area() + + # Status label + status_label = Gtk.Label(label="AI is analyzing your request...") + status_label.set_halign(Gtk.Align.START) + content_area.pack_start(status_label, False, False, 10) + + # Analysis text view + scrolled = Gtk.ScrolledWindow() + scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled.set_size_request(550, 300) + + text_view = Gtk.TextView() + text_view.set_editable(False) + text_view.set_wrap_mode(Gtk.WrapMode.WORD) + scrolled.add(text_view) + content_area.pack_start(scrolled, True, True, 10) + + # Store references for updating + self._action_dialog = dialog + self._action_status_label = status_label + self._action_text_view = text_view + self._action_execute_button = execute_button + self._current_action_request = action_request + + # Show everything + dialog.show_all() + + # Set up response handler + def on_response(dialog, response_id): + if response_id == Gtk.ResponseType.ACCEPT: + # Execute the confirmed action + if hasattr(self, '_parsed_action'): + # Close dialog FIRST, then execute action + dialog.destroy() + # Add small delay to let dialog close + from gi.repository import GLib + GLib.timeout_add(500, lambda: self._execute_confirmed_action(self._parsed_action)) + else: + dialog.destroy() + + dialog.connect("response", on_response) + + # Start AI analysis in background + import threading + analysis_thread = threading.Thread( + target=self._analyze_action_request, + args=(action_request,) + ) + analysis_thread.daemon = True + analysis_thread.start() + + # Show dialog (non-blocking) + dialog.present() + + except Exception as e: + logger.error(f"Error showing confirmation dialog: {e}") + self._present_message(f"Error showing confirmation dialog: {e}") + + def _transform_dialog_for_action_analysis(self, dialog, action_request): + """Transform action dialog to show AI analysis and confirmation.""" + try: + # Clear existing content + content_area = dialog.get_content_area() + for child in content_area.get_children(): + content_area.remove(child) + + # Clear existing buttons and add new ones + action_area = dialog.get_action_area() + for child in action_area.get_children(): + child.destroy() # Use destroy instead of remove + + # Add new buttons with proper accessibility + cancel_button = Gtk.Button.new_with_label("Cancel") + execute_button = Gtk.Button.new_with_label("Execute Action") + + # Set up button responses + cancel_button.connect("clicked", lambda b: dialog.response(Gtk.ResponseType.CANCEL)) + execute_button.connect("clicked", lambda b: dialog.response(Gtk.ResponseType.ACCEPT)) + + # Add buttons to action area + action_area.pack_start(cancel_button, False, False, 0) + action_area.pack_start(execute_button, False, False, 0) + + # Make buttons accessible and focusable + cancel_button.set_can_focus(True) + execute_button.set_can_focus(True) + execute_button.set_sensitive(False) # Disabled until analysis complete + + # Set default response for Enter key + dialog.set_default_response(Gtk.ResponseType.ACCEPT) + execute_button.set_can_default(True) + execute_button.grab_default() + + # Status label + status_label = Gtk.Label(label="AI is analyzing your request...") + status_label.set_halign(Gtk.Align.START) + content_area.pack_start(status_label, False, False, 10) + + # Analysis text view + scrolled = Gtk.ScrolledWindow() + scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled.set_size_request(550, 200) + + text_view = Gtk.TextView() + text_view.set_editable(False) + text_view.set_wrap_mode(Gtk.WrapMode.WORD) + scrolled.add(text_view) + content_area.pack_start(scrolled, True, True, 10) + + # Store references for updating + self._action_dialog = dialog + self._action_status_label = status_label + self._action_text_view = text_view + self._action_execute_button = execute_button + self._current_action_request = action_request + + # Show all widgets including new buttons + cancel_button.show() + execute_button.show() + dialog.show_all() + + # Start AI analysis in background + import threading + analysis_thread = threading.Thread( + target=self._analyze_action_request, + args=(action_request,) + ) + analysis_thread.daemon = True + analysis_thread.start() + + # Set up response handlers + def on_response(dialog, response_id): + if response_id == Gtk.ResponseType.ACCEPT: + # Execute the confirmed action + if hasattr(self, '_parsed_action'): + self._execute_confirmed_action(self._parsed_action) + dialog.destroy() + + dialog.connect("response", on_response) + + except Exception as e: + logger.error(f"Error transforming action dialog: {e}") + dialog.destroy() + self._present_message(f"Error in action dialog: {e}") + + def _analyze_action_request(self, action_request): + """Analyze action request using AI (runs in background thread).""" + try: + logger.info(f"Analyzing action request: {action_request}") + + # Use AI to analyze the request + analysis = self._ai_provider.suggest_actions( + action_request, + self._current_screen_data.get('screenshot'), + self._current_screen_data.get('accessibility') + ) + + # Update UI on main thread + from gi.repository import GLib + GLib.idle_add(self._update_action_analysis, analysis) + + except Exception as e: + logger.error(f"Error analyzing action request: {e}") + from gi.repository import GLib + GLib.idle_add(self._update_action_analysis, f"Error analyzing request: {e}") + + def _update_action_analysis(self, analysis): + """Update action dialog with AI analysis results.""" + try: + if not hasattr(self, '_action_dialog'): + return False + + # Update status + self._action_status_label.set_text("AI Analysis Complete:") + + # Update analysis text + buffer = self._action_text_view.get_buffer() + buffer.set_text(analysis) + + # Enable execute button if analysis looks successful + if not analysis.startswith("Error"): + self._action_execute_button.set_sensitive(True) + self._parsed_action = self._parse_action_response(analysis) + # Set focus to execute button so user can press Enter + self._action_execute_button.grab_focus() + self._action_execute_button.grab_default() + logger.info("Execute button enabled and focused") + else: + logger.error(f"Analysis failed: {analysis}") + + self._present_message("Action analysis complete. Review and confirm in dialog. Press Tab to navigate, Enter to execute, Escape to cancel.") + + except Exception as e: + logger.error(f"Error updating action analysis: {e}") + + return False # Don't repeat idle callback + + def _parse_action_response(self, analysis): + """Parse AI action response into executable commands.""" + try: + # Look for structured ACTION TYPE in AI response + action_data = { + 'type': 'unknown', + 'target': None, + 'value': None, + 'coordinates': None, + 'description': analysis + } + + analysis_lower = analysis.lower() + + # Look for explicit ACTION TYPE markers first + if '**action type**:' in analysis_lower: + import re + action_type_match = re.search(r'\*\*action type\*\*:\s*(\w+)', analysis_lower) + if action_type_match: + action_type = action_type_match.group(1).lower() + if action_type in ['click', 'type', 'copy', 'scroll', 'navigate']: + action_data['type'] = action_type + logger.info(f"Detected action type from AI response: {action_type}") + return action_data + + # Fallback: Look for action keywords in the original user request + if hasattr(self, '_current_action_request'): + request_lower = self._current_action_request.lower() + logger.info(f"Parsing user request: {self._current_action_request}") + + # Check user request directly + if 'copy' in request_lower and 'clipboard' in request_lower: + action_data['type'] = 'copy' + logger.info("Detected COPY action from user request") + elif 'type' in request_lower or 'enter' in request_lower: + action_data['type'] = 'type' + logger.info("Detected TYPE action from user request") + elif 'click' in request_lower: + action_data['type'] = 'click' + logger.info("Detected CLICK action from user request") + + # Final fallback: analyze AI response content + if action_data['type'] == 'unknown': + if 'click' in analysis_lower: + action_data['type'] = 'click' + elif 'type' in analysis_lower or 'typewrite' in analysis_lower: + action_data['type'] = 'type' + elif 'copy' in analysis_lower or 'clipboard' in analysis_lower: + action_data['type'] = 'copy' + + logger.info(f"Final parsed action type: {action_data['type']}") + return action_data + + except Exception as e: + logger.error(f"Error parsing action response: {e}") + return {'type': 'error', 'description': str(e)} + + def _execute_confirmed_action(self, action_data): + """Execute the user-confirmed action.""" + try: + logger.info(f"Executing confirmed action: {action_data}") + + action_type = action_data.get('type', 'unknown') + + if action_type == 'click': + result = self._perform_click_action(action_data) + elif action_type == 'type': + result = self._perform_type_action(action_data) + elif action_type == 'copy': + result = self._perform_copy_action(action_data) + else: + result = f"Unknown action type: {action_type}" + + self._present_message(f"Action result: {result}") + + except Exception as e: + logger.error(f"Error executing action: {e}") + self._present_message(f"Error executing action: {e}") + + def _perform_click_action(self, action_data): + """Perform a click action on a UI element.""" + try: + # Try PyAutoGUI for universal clicking + import pyautogui + + # Extract coordinates from action_data or current screen data + coords = action_data.get('coordinates') + if not coords and hasattr(self, '_current_screen_data'): + # Look for actionable elements in the collected data + actionable_elements = self._current_screen_data.get('accessibility', {}).get('actionable_elements', []) + # For now, just click center of screen as fallback + coords = {'center_x': 640, 'center_y': 360} + + if coords: + x, y = coords.get('center_x', 640), coords.get('center_y', 360) + pyautogui.click(x, y) + return f"Clicked at coordinates ({x}, {y})" + else: + return "Could not determine click coordinates" + + except ImportError: + return "PyAutoGUI not available - install with: pip install pyautogui" + except Exception as e: + return f"Click failed: {e}" + + def _perform_type_action(self, action_data): + """Perform a text typing action.""" + try: + import pyautogui + + # Extract text to type from the action description + text_to_type = self._extract_text_from_action(action_data) + logger.info(f"Attempting to type: '{text_to_type}'") + + if text_to_type: + import time + + # Simple approach: Just wait a moment for dialogs to settle, then type + # Since PyAutoGUI works fine when terminal is focused, let's not overthink it + logger.info("Waiting briefly for focus to settle before typing") + time.sleep(1.0) # Give time for any dialogs to close and focus to return + + # Disable PyAutoGUI failsafe for this operation + pyautogui.FAILSAFE = False + + logger.info(f"Starting to type '{text_to_type}' to focused application") + + # Type the text with more reasonable timing + pyautogui.typewrite(text_to_type, interval=0.05) + + # Check if we should press Enter + request_lower = getattr(self, '_current_action_request', '').lower() + description_lower = action_data.get('description', '').lower() + + if ('press enter' in request_lower or 'hit enter' in request_lower or + 'and enter' in request_lower or 'press enter' in description_lower): + time.sleep(0.1) + pyautogui.press('return') + logger.info("Pressed Enter after typing") + return f"Typed '{text_to_type}' and pressed Enter" + else: + return f"Typed '{text_to_type}'" + else: + return "Could not determine text to type" + + except ImportError: + return "PyAutoGUI not available - install with: pip install pyautogui" + except Exception as e: + logger.error(f"Type action failed: {e}") + return f"Type action failed: {e}" + + def _perform_copy_action(self, action_data): + """Perform a copy to clipboard action.""" + try: + # Extract the specific text to copy from the user's request + text_to_copy = self._extract_text_to_copy(action_data) + + if text_to_copy: + # Use direct clipboard manipulation instead of Ctrl+C + import subprocess + + # Use xclip on Linux (works on both X11 and Wayland via XWayland) + try: + process = subprocess.Popen(['xclip', '-selection', 'clipboard'], + stdin=subprocess.PIPE, + text=True) + process.communicate(input=text_to_copy) + return f"Copied '{text_to_copy}' to clipboard" + except FileNotFoundError: + # Fallback to wl-copy for pure Wayland + try: + process = subprocess.Popen(['wl-copy'], + stdin=subprocess.PIPE, + text=True) + process.communicate(input=text_to_copy) + return f"Copied '{text_to_copy}' to clipboard" + except FileNotFoundError: + return "Neither xclip nor wl-copy available for clipboard operations" + else: + # Fallback: try to copy whatever is currently selected + import pyautogui + pyautogui.hotkey('ctrl', 'c') + return "Copied current selection to clipboard" + + except ImportError: + return "Required clipboard tools not available" + except Exception as e: + return f"Copy action failed: {e}" + + def _extract_text_to_copy(self, action_data): + """Extract the specific text to copy from the user request.""" + try: + if hasattr(self, '_current_action_request'): + request = self._current_action_request + request_lower = request.lower() + + # Special case: summarize and copy requests + if 'summar' in request_lower and ('clipboard' in request_lower or 'copy' in request_lower): + summary = self._generate_screen_summary() + if summary: + logger.info("Generated screen summary for clipboard") + return summary + + # Look for quoted text + import re + quoted_matches = re.findall(r'["\']([^"\']+)["\']', request) + if quoted_matches: + return quoted_matches[0] + + # Look for text after "copy" + copy_matches = re.findall(r'copy\s+(.+?)\s+to\s+clipboard', request, re.IGNORECASE) + if copy_matches: + return copy_matches[0].strip('"\'') + + return None + + except Exception as e: + logger.error(f"Error extracting text to copy: {e}") + return None + + def _generate_screen_summary(self): + """Generate a summary of the current screen for clipboard operations.""" + try: + if hasattr(self, '_current_screen_data') and self._current_screen_data: + accessibility_data = self._current_screen_data.get('accessibility', {}) + + # Build a simple summary + summary_parts = [] + + # Application info + app_name = self._current_screen_data.get('application', 'Unknown Application') + summary_parts.append(f"Application: {app_name}") + + # Focus info + focus_info = accessibility_data.get('focus', {}) + if focus_info: + focus_name = focus_info.get('name', '') + focus_role = focus_info.get('role', '') + if focus_name or focus_role: + summary_parts.append(f"Current focus: {focus_name} ({focus_role})") + + # Context info + context = accessibility_data.get('context', []) + if context and len(context) > 0: + parent_info = context[0] + parent_name = parent_info.get('name', '') + parent_role = parent_info.get('role', '') + if parent_name or parent_role: + summary_parts.append(f"In: {parent_name} ({parent_role})") + + # Actionable elements count + actionable_elements = accessibility_data.get('actionable_elements', []) + if actionable_elements: + summary_parts.append(f"Available actions: {len(actionable_elements)} interactive elements") + + if summary_parts: + return '\n'.join(summary_parts) + else: + return f"Screen summary for {app_name} - focused on accessible content" + + return "Unable to generate screen summary - no data available" + + except Exception as e: + logger.error(f"Error generating screen summary: {e}") + return f"Screen summary generation failed: {e}" + + def _extract_text_from_action(self, action_data): + """Extract text to type from action description.""" + try: + # First try the original user request (most reliable) + if hasattr(self, '_current_action_request'): + request = self._current_action_request + logger.info(f"Extracting text from user request: {request}") + + import re + + # Enhanced extraction for commands like "type echo 'hello world'" + if request.lower().startswith('type '): + # Remove "type " from the beginning + text = request[5:].strip() + + # Remove trailing conditions like "and press enter", "in the terminal" + text = re.sub(r'\s+and\s+(press\s+)?enter.*$', '', text, flags=re.IGNORECASE) + text = re.sub(r'\s+in\s+.+$', '', text, flags=re.IGNORECASE) + + logger.info(f"Extracted command after 'type ': '{text}'") + return text + + # Look for quoted text in various formats + quoted_patterns = [ + r'"([^"]*)"', # Double quotes + r"'([^']*)'", # Single quotes + r'`([^`]*)`' # Backticks + ] + + for pattern in quoted_patterns: + matches = re.findall(pattern, request) + if matches: + text = matches[0] + logger.info(f"Found quoted text: '{text}'") + return text + + # Look for text after "type" with flexible matching + type_patterns = [ + r'type\s+(.+?)(?:\s+and\s+|\s+in\s+|\s*$)', # type X and... or type X in... + r'enter\s+(.+?)(?:\s+into\s+|\s*$)', # enter X into... + ] + + for pattern in type_patterns: + matches = re.findall(pattern, request, re.IGNORECASE) + if matches: + text = matches[0].strip() + logger.info(f"Found text with pattern '{pattern}': '{text}'") + return text + + # Fallback: try the AI description for quoted text + description = action_data.get('description', '') + if description: + import re + quoted_matches = re.findall(r'"([^"]*)"', description) + if quoted_matches: + logger.info(f"Found text in AI description: '{quoted_matches[0]}'") + return quoted_matches[0] + + logger.warning("Could not extract text to type") + return None + + except Exception as e: + logger.error(f"Error extracting text from action: {e}") + return None + + +class AIAssistantMenu(Gtk.Dialog): + """A dialog containing AI Assistant options.""" + + def __init__(self, handler): + super().__init__(title="AI Assistant", transient_for=None, flags=0) + self.on_option_selected = handler + + # Set dialog properties for better screen reader accessibility + self.set_modal(True) + self.set_position(Gtk.WindowPosition.CENTER) + self.set_default_size(350, 250) + + # Add OK and Cancel buttons + self.add_button("OK", Gtk.ResponseType.OK) + self.add_button("Cancel", Gtk.ResponseType.CANCEL) + + # Connect response signal + self.connect("response", self._on_response) + + # Add content to dialog + content_area = self.get_content_area() + + # Add label + label = Gtk.Label(label="Choose an AI Assistant action:") + content_area.pack_start(label, False, False, 10) + + # Create radio button group for options + self.radio_ask = Gtk.RadioButton.new_with_label(None, "Ask Question") + self.radio_describe = Gtk.RadioButton.new_with_label_from_widget(self.radio_ask, "Describe Screen") + self.radio_action = Gtk.RadioButton.new_with_label_from_widget(self.radio_ask, "Request Action") + + # Pack radio buttons + content_area.pack_start(self.radio_ask, False, False, 5) + content_area.pack_start(self.radio_describe, False, False, 5) + content_area.pack_start(self.radio_action, False, False, 5) + + # Set first option as selected by default + self.radio_ask.set_active(True) + + # Connect keyboard events for Enter key handling + self.connect("key-press-event", self._on_key_press) + + print("DEBUG: AIAssistantMenu dialog created with radio buttons") + + def _on_response(self, dialog, response_id): + """Handler for dialog response.""" + print(f"DEBUG: Dialog response: {response_id}") + + if response_id == Gtk.ResponseType.OK: + # Determine which radio button is selected + if self.radio_ask.get_active(): + action_id = "ask_question" + elif self.radio_describe.get_active(): + action_id = "describe_screen" + elif self.radio_action.get_active(): + action_id = "request_action" + else: + action_id = None + + if action_id: + print(f"DEBUG: Selected action: {action_id}") + self.on_option_selected(action_id) + + self.destroy() + + def _on_key_press(self, widget, event): + """Handle key press events.""" + # Allow Enter key to activate OK button + if event.keyval == 65293: # Enter key + self.response(Gtk.ResponseType.OK) + return True + return False + + def show_gui(self): + """Shows the AI Assistant dialog.""" + try: + print("DEBUG: Starting dialog show_gui") + self.show_all() + print("DEBUG: Dialog show_all() called - should be visible and accessible now") + + # Present the dialog to ensure it gets focus + self.present() + print("DEBUG: Dialog presented") + + except Exception as e: + print(f"DEBUG: Error in show_gui: {e}") + import traceback + traceback.print_exc() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.info new file mode 100644 index 0000000..dc61076 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.info @@ -0,0 +1,8 @@ +name = Bye Cthulhu +version = 1.0.0 +description = Says goodbye when Cthulhu is shutting down +authors = Stormux +website = https://stormux.org +copyright = Copyright 2025 +builtin = false +hidden = false \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.py new file mode 100644 index 0000000..d3174ea --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/ByeCthulhu/plugin.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""Bye Cthulhu plugin for Cthulhu.""" + +import logging +import time +from cthulhu.plugin import Plugin, cthulhu_hookimpl + +logger = logging.getLogger(__name__) + +class ByeCthulhu(Plugin): + """Plugin that speaks a goodbye message when Cthulhu is shutting down.""" + + def __init__(self, *args, **kwargs): + """Initialize the plugin.""" + super().__init__(*args, **kwargs) + logger.info("ByeCthulhu plugin initialized") + self._signal_handler_id = None + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin.""" + # Skip if this activation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Activating ByeCthulhu plugin") + try: + # Connect to the stop-application-completed signal + signal_manager = self.app.getSignalManager() + self._signal_handler_id = signal_manager.connectSignal( + "stop-application-completed", + self.process, + "default" # Add profile parameter + ) + except Exception as e: + logger.error(f"Error activating ByeCthulhu plugin: {e}") + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin.""" + # Skip if this deactivation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Deactivating ByeCthulhu plugin") + try: + # Disconnect signal if we have an ID + if self._signal_handler_id is not None: + signal_manager = self.app.getSignalManager() + # Use disconnectSignalByFunction instead since disconnectSignal doesn't exist + signal_manager.disconnectSignalByFunction( + self.process + ) + self._signal_handler_id = None + except Exception as e: + logger.error(f"Error deactivating ByeCthulhu plugin: {e}") + + def process(self, app): + """Process the stop-application-completed signal.""" + try: + messages = app.getDynamicApiManager().getAPI('Messages') + state = app.getDynamicApiManager().getAPI('CthulhuState') + if state.activeScript: + state.activeScript.presentationInterrupt() + state.activeScript.presentMessage(messages.STOP_CTHULHU, resetStyles=False) + except Exception as e: + logger.error(f"Error in ByeCthulhu process: {e}") \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/__init__.py new file mode 100644 index 0000000..9531613 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Clipboard plugin package.""" + +from .plugin import Clipboard + +__all__ = ['Clipboard'] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.info new file mode 100644 index 0000000..0e15232 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.info @@ -0,0 +1,7 @@ +[Plugin] +Name = Clipboard +Module = Clipboard +Description = Present the content of the current clipboard +Authors = Storm Dragon +Version = 1.0 +Category = Utilities diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.py new file mode 100644 index 0000000..27e2f4e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/Clipboard/plugin.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Clipboard plugin for Cthulhu.""" + +import os +import logging +import gettext +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, Gdk + +from cthulhu.plugin import Plugin, cthulhu_hookimpl + +# Set up translation function +_ = gettext.gettext + +logger = logging.getLogger(__name__) + +class Clipboard(Plugin): + """Plugin to read the clipboard contents.""" + + def __init__(self, *args, **kwargs): + """Initialize the plugin.""" + super().__init__(*args, **kwargs) + logger.info("Clipboard plugin initialized") + self._signal_handler_id = None + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin.""" + # Skip if this activation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Activating Clipboard plugin") + try: + # Register keyboard shortcut + self.registerGestureByString(self.speakClipboard, _('clipboard'), 'kb:cthulhu+shift+c') + logger.debug("Registered shortcut for clipboard") + except Exception as e: + logger.error(f"Error activating Clipboard plugin: {e}") + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin.""" + # Skip if this deactivation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Deactivating Clipboard plugin") + # Note: Currently no unregister method needed as keybindings are managed by APIHelper + + def speakClipboard(self, script=None, inputEvent=None): + """Present the contents of the clipboard.""" + try: + message = self.getClipboard() + + state = self.app.getDynamicApiManager().getAPI('CthulhuState') + if state and state.activeScript: + state.activeScript.presentMessage(message, resetStyles=False) + logger.debug("Presented clipboard contents") + else: + logger.warning("Could not present clipboard: no active script") + + return True + except Exception as e: + logger.error(f"Error in speakClipboard: {e}") + return False + + def getClipboard(self): + """Get the contents of the clipboard.""" + try: + message = "" + found_clipboard_content = False + + # Get Clipboard + clipboard_obj = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + + clipboard_text = clipboard_obj.wait_for_text() + clipboard_image = clipboard_obj.wait_for_image() + clipboard_uri = clipboard_obj.wait_for_uris() + + if clipboard_text is not None: + found_clipboard_content = True + + if clipboard_obj.wait_is_uris_available(): + no_of_objects = 0 + no_of_folder = 0 + no_of_files = 0 + no_of_disks = 0 + no_of_links = 0 + + for uri in clipboard_uri: + if uri == '': + continue + + no_of_objects += 1 + uri_without_protocol = uri[uri.find('://') + 3:] + message += " " + uri[uri.rfind('/') + 1:] + " " + + if os.path.isdir(uri_without_protocol): + no_of_folder += 1 + message = message + _("Folder") + + if os.path.isfile(uri_without_protocol): + no_of_files += 1 + message = message + _("File") + + if os.path.ismount(uri_without_protocol): + no_of_disks += 1 + message = message + _("Disk") + + if os.path.islink(uri_without_protocol): + no_of_links += 1 + message = message + _("Link") + + if no_of_objects > 1: + message = str(no_of_objects) + _(" Objects in clipboard ") + message + else: + message = str(no_of_objects) + _(" Object in clipboard ") + message + else: + message = _("Text in clipboard ") + clipboard_text + + if clipboard_image is not None: + found_clipboard_content = True + message = _("The clipboard contains a image") + + if not found_clipboard_content: + message = _("The clipboard is empty") + + return message + except Exception as e: + logger.error(f"Error getting clipboard content: {e}") + return _("Error accessing clipboard") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.info new file mode 100644 index 0000000..1ed4e67 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.info @@ -0,0 +1,8 @@ +name = Display Version +version = 1.0.0 +description = Announces the Cthulhu version with Cthulhu+Shift+V +authors = Stormux +website = https://stormux.org +copyright = Copyright 2025 +builtin = false +hidden = false \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.py new file mode 100644 index 0000000..b3a80e5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/DisplayVersion/plugin.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""Display Version plugin for Cthulhu.""" + +import logging +from cthulhu.plugin import Plugin, cthulhu_hookimpl +from cthulhu import cthulhuVersion +from cthulhu import debug + +logger = logging.getLogger(__name__) + +class DisplayVersion(Plugin): + """Plugin that announces the current Cthulhu version.""" + + def __init__(self, *args, **kwargs): + """Initialize the plugin.""" + super().__init__(*args, **kwargs) + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: Plugin initialized", True) + self._kb_binding = None + self._activated = False + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin.""" + # Skip if this activation call isn't for us + if plugin is not None and plugin is not self: + return + + # Prevent duplicate activation + if self._activated: + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: Already activated, skipping", True) + return + + try: + # Use debug.printMessage to ensure it goes to the main debug log + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: Plugin activation starting", True) + debug.printMessage(debug.LEVEL_INFO, f"DisplayVersion: Plugin name: {self.name}", True) + + # Check if we have access to the API helper + if not self.app: + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: ERROR - No app reference available!", True) + return + + # Register keyboard shortcut + gesture_string = 'kb:cthulhu+shift+v' + debug.printMessage(debug.LEVEL_INFO, f"DisplayVersion: Registering gesture: {gesture_string}", True) + + self._kb_binding = self.registerGestureByString( + self.speakText, + f'Cthulhu screen reader version {cthulhuVersion.version}-{cthulhuVersion.codeName}', + gesture_string + ) + + if self._kb_binding: + debug.printMessage(debug.LEVEL_INFO, f"DisplayVersion: Keybinding registered successfully", True) + else: + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: ERROR - Failed to create keybinding!", True) + + self._activated = True + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: Plugin activation completed", True) + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"DisplayVersion: ERROR activating plugin: {e}", True) + import traceback + debug.printMessage(debug.LEVEL_INFO, f"DisplayVersion: {traceback.format_exc()}", True) + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin.""" + # Skip if this deactivation call isn't for us + if plugin is not None and plugin is not self: + return + + self._activated = False + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: Plugin deactivated", True) + + def speakText(self, script=None, inputEvent=None): + """Speak the Cthulhu version when shortcut is pressed.""" + try: + debug.printMessage(debug.LEVEL_INFO, "DisplayVersion: speakText called", True) + if self.app: + state = self.app.getDynamicApiManager().getAPI('CthulhuState') + if state.activeScript: + state.activeScript.presentMessage( + f'Cthulhu screen reader version {cthulhuVersion.version}-{cthulhuVersion.codeName}', + resetStyles=False + ) + return True + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"DisplayVersion: ERROR in speakText: {e}", True) + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.info new file mode 100644 index 0000000..f1faf33 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.info @@ -0,0 +1,7 @@ +[Plugin] +Name = Cthulhu say hello +Module = HelloCthulhu +Description = Startup announcement for Cthulhu +Authors = Storm Dragon +Version = 1.0 +Category = Interaction diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.py new file mode 100644 index 0000000..a790757 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/HelloCthulhu/plugin.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# +# 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. +# + +"""Hello Cthulhu plugin for Cthulhu.""" + +import logging +import weakref +from cthulhu.plugin import Plugin, cthulhu_hookimpl + +logger = logging.getLogger(__name__) + +# Class-level variable to track if the greeting has been presented +# This ensures the greeting is only shown once even if multiple instances exist +_greeting_shown = False + +class HelloCthulhu(Plugin): + """Plugin that speaks a welcome message when Cthulhu starts up.""" + + def __init__(self, *args, **kwargs): + """Initialize the plugin.""" + super().__init__(*args, **kwargs) + logger.info("HelloCthulhu plugin initialized") + self._signal_handler_id = None + self._is_connected = False + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin.""" + # Skip if this activation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Activating HelloCthulhu plugin") + try: + # Only connect the signal if we haven't already + if not self._is_connected: + signal_manager = self.app.getSignalManager() + self._signal_handler_id = signal_manager.connectSignal( + "start-application-completed", + self.process, + "default" # Add profile parameter + ) + self._is_connected = True + logger.debug("Connected to start-application-completed signal") + except Exception as e: + logger.error(f"Error activating HelloCthulhu plugin: {e}") + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin.""" + # Skip if this deactivation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Deactivating HelloCthulhu plugin") + try: + # Only disconnect if we're connected + if self._is_connected and self._signal_handler_id is not None: + signal_manager = self.app.getSignalManager() + signal_manager.disconnectSignalByFunction( + self.process + ) + self._signal_handler_id = None + self._is_connected = False + logger.debug("Disconnected from start-application-completed signal") + except Exception as e: + logger.error(f"Error deactivating HelloCthulhu plugin: {e}") + + def process(self, app): + """Process the start-application-completed signal.""" + global _greeting_shown + + # Only present the message if it hasn't been shown yet + if _greeting_shown: + logger.debug("Greeting already shown, skipping") + return + + try: + messages = app.getDynamicApiManager().getAPI('Messages') + state = app.getDynamicApiManager().getAPI('CthulhuState') + if state.activeScript: + state.activeScript.presentMessage(messages.START_CTHULHU, resetStyles=False) + _greeting_shown = True + logger.info("Greeting message presented") + + # Disconnect the signal after presenting the message + if self._is_connected and self._signal_handler_id is not None: + signal_manager = app.getSignalManager() + signal_manager.disconnectSignalByFunction( + self.process + ) + self._signal_handler_id = None + self._is_connected = False + logger.debug("Disconnected signal after presenting greeting") + except Exception as e: + logger.error(f"Error in HelloCthulhu process: {e}") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/__init__.py new file mode 100644 index 0000000..7e5fc5a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/__init__.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""IndentationAudio plugin package.""" + +from .plugin import IndentationAudio + +__all__ = ['IndentationAudio'] \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.info new file mode 100644 index 0000000..b3e61ec --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.info @@ -0,0 +1,8 @@ +name = IndentationAudio +version = 1.0.0 +description = Provides audio feedback for indentation level changes when navigating code or text +authors = Stormux +website = https://git.stormux.org/storm/cthulhu +copyright = Copyright 2025 +builtin = false +hidden = false \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.py new file mode 100644 index 0000000..84318ad --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/IndentationAudio/plugin.py @@ -0,0 +1,478 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""IndentationAudio plugin for Cthulhu - Provides audio feedback for indentation level changes.""" + +import logging +import re +from gi.repository import GLib + +from cthulhu.plugin import Plugin, cthulhu_hookimpl +from cthulhu import debug + +# Import Cthulhu's sound system +try: + from cthulhu import sound + from cthulhu.sound_generator import Tone + SOUND_AVAILABLE = True +except ImportError as e: + SOUND_AVAILABLE = False + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Sound import failed: {e}", True) + +logger = logging.getLogger(__name__) + + +class IndentationAudio(Plugin): + """Plugin that provides audio cues for indentation level changes.""" + + def __init__(self, *args, **kwargs): + """Initialize the IndentationAudio plugin.""" + super().__init__(*args, **kwargs) + self._enabled = True # Start enabled by default + self._last_indentation_level = {} # Track per-object indentation + self._event_listener_id = None + self._kb_binding = None + # Audio settings + self._base_frequency = 200 # Base frequency in Hz + self._frequency_step = 80 # Hz per indentation level + self._tone_duration = 0.15 # Seconds + self._max_frequency = 1200 # Cap frequency to avoid harsh sounds + + self._activated = False + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Plugin initialized", True) + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the IndentationAudio plugin.""" + if plugin is not None and plugin is not self: + return + + # Prevent duplicate activation + if self._activated: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Already activated, skipping", True) + return + + try: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Plugin activation starting", True) + + # Initialize sound player + if SOUND_AVAILABLE: + self._player = sound.getPlayer() + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Sound player initialized", True) + else: + self._player = None + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Sound not available", True) + + # Register keybinding for toggle (Cthulhu+I) + self._register_keybinding() + + # Connect to text caret movement events + self._connect_to_events() + + self._activated = True + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Plugin activated successfully", True) + return True + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: ERROR activating plugin: {e}", True) + return False + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the IndentationAudio plugin.""" + if plugin is not None and plugin is not self: + return + + try: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Plugin deactivation starting", True) + + # Disconnect from events + self._disconnect_from_events() + + # Clear tracking data + self._last_indentation_level.clear() + + self._activated = False + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Plugin deactivated successfully", True) + return True + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: ERROR deactivating plugin: {e}", True) + return False + + def _register_keybinding(self): + """Register the Cthulhu+I keybinding for toggling the plugin.""" + try: + if not self.app: + logger.error("IndentationAudio: No app reference available for keybinding") + return + + # Register Cthulhu+I keybinding using the plugin's registerGestureByString method + gesture_string = "kb:cthulhu+i" + description = "Toggle indentation audio feedback" + + self._kb_binding = self.registerGestureByString( + self._toggle_indentation_audio, + description, + gesture_string + ) + + if self._kb_binding: + logger.info(f"IndentationAudio: Registered keybinding {gesture_string}") + logger.info(f"Binding keysymstring: {self._kb_binding.keysymstring}") + logger.info(f"Binding modifiers: {self._kb_binding.modifiers}") + else: + logger.error(f"IndentationAudio: Failed to register keybinding {gesture_string}") + + except Exception as e: + logger.error(f"IndentationAudio: Error registering keybinding: {e}") + + def _connect_to_events(self): + """Connect to text navigation events.""" + try: + # Hook into the dynamic API to make ourselves available to scripts + if self.app: + api_manager = self.app.getDynamicApiManager() + api_manager.registerAPI('IndentationAudioPlugin', self) + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Registered with dynamic API manager", True) + + # Try to connect to ATSPI events directly + self._connect_to_atspi_events() + + except Exception as e: + logger.error(f"IndentationAudio: Error connecting to events: {e}") + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Error connecting to events: {e}", True) + + def _connect_to_atspi_events(self): + """Connect to ATSPI caret movement events.""" + try: + # Import ATSPI event system + from gi.repository import Atspi + + # Register for text caret movement events + self._event_listener = Atspi.EventListener.new(self._on_caret_moved) + Atspi.EventListener.register(self._event_listener, "object:text-caret-moved") + + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Registered for text-caret-moved events", True) + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: ATSPI connection error: {e}", True) + + def _on_caret_moved(self, event): + """Handle caret movement events.""" + try: + if not self._enabled: + return + + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Caret moved in {event.source}", True) + + # Use Cthulhu's script system to get line text + try: + from cthulhu import cthulhu_state + + # Get current active script + if cthulhu_state.activeScript: + script = cthulhu_state.activeScript + obj = event.source + + # Use script's getTextLineAtCaret method + if hasattr(script, 'getTextLineAtCaret'): + line, caret_offset, start_offset = script.getTextLineAtCaret(obj) + if line is not None: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Line navigation - line: '{line}'", True) + self.check_indentation_change(obj, line) + else: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: getTextLineAtCaret returned None", True) + else: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: script has no getTextLineAtCaret method", True) + else: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: No active script available", True) + + except Exception as script_e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Error using script method: {script_e}", True) + + # Fallback to direct AT-SPI access + try: + obj = event.source + if obj and hasattr(obj, 'queryText'): + text_iface = obj.queryText() + if text_iface: + # Get all text and find current line + full_text = text_iface.getText(0, -1) + caret_pos = text_iface.caretOffset + + if full_text: + lines = full_text.split('\n') + char_count = 0 + for line in lines: + if char_count <= caret_pos <= char_count + len(line): + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Fallback line: '{line}'", True) + self.check_indentation_change(obj, line) + break + char_count += len(line) + 1 # +1 for newline + + except Exception as fallback_e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Fallback also failed: {fallback_e}", True) + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Error in caret moved handler: {e}", True) + + def _disconnect_from_events(self): + """Disconnect from text navigation events.""" + try: + # Unregister ATSPI event listener + if hasattr(self, '_event_listener') and self._event_listener: + from gi.repository import Atspi + Atspi.EventListener.deregister(self._event_listener, "object:text-caret-moved") + self._event_listener = None + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Unregistered ATSPI events", True) + + # Unregister from dynamic API + if self.app: + api_manager = self.app.getDynamicApiManager() + api_manager.unregisterAPI('IndentationAudioPlugin') + + except Exception as e: + logger.error(f"IndentationAudio: Error disconnecting from events: {e}") + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Error disconnecting: {e}", True) + + def _monkey_patch_script_methods(self): + """Monkey-patch the default script's line navigation methods.""" + try: + # Get the current active script + if self.app: + state = self.app.getDynamicApiManager().getAPI('CthulhuState') + if state and hasattr(state, 'activeScript') and state.activeScript: + script = state.activeScript + + # Store original method + if hasattr(script, 'sayLine'): + self._original_sayLine = script.sayLine + + # Create wrapped version + def wrapped_sayLine(obj): + # Call original method first + result = self._original_sayLine(obj) + + # Add our indentation audio check + try: + line, caretOffset, startOffset = script.getTextLineAtCaret(obj) + self.check_indentation_change(obj, line) + except Exception as e: + logger.error(f"IndentationAudio: Error in wrapped_sayLine: {e}") + + return result + + # Replace the method + script.sayLine = wrapped_sayLine + logger.info("IndentationAudio: Successfully monkey-patched sayLine method") + + except Exception as e: + logger.error(f"IndentationAudio: Error monkey-patching script methods: {e}") + + def _restore_script_methods(self): + """Restore original script methods.""" + try: + if self.app and hasattr(self, '_original_sayLine'): + state = self.app.getDynamicApiManager().getAPI('CthulhuState') + if state and hasattr(state, 'activeScript') and state.activeScript: + script = state.activeScript + if hasattr(script, 'sayLine'): + script.sayLine = self._original_sayLine + logger.info("IndentationAudio: Restored original sayLine method") + + except Exception as e: + logger.error(f"IndentationAudio: Error restoring script methods: {e}") + + def _toggle_indentation_audio(self, script, inputEvent=None): + """Toggle the indentation audio feedback on/off.""" + try: + self._enabled = not self._enabled + state = "enabled" if self._enabled else "disabled" + + # Announce the state change + message = f"Indentation audio {state}" + if hasattr(script, 'speakMessage'): + script.speakMessage(message) + + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Toggled to {state}", True) + + # Test the indentation detection on current line when enabled + if self._enabled and script: + try: + # Try to get current focus object and line text + from cthulhu import cthulhu_state + obj = cthulhu_state.locusOfFocus + if obj and hasattr(script, 'getTextLineAtCaret'): + line, caretOffset, startOffset = script.getTextLineAtCaret(obj) + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Testing with current line: '{line}'", True) + self.check_indentation_change(obj, line) + else: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Could not get focus object or getTextLineAtCaret method", True) + except Exception as test_e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Test failed: {test_e}", True) + + logger.info(f"IndentationAudio: Toggled to {state}") + return True + + except Exception as e: + logger.error(f"IndentationAudio: Error toggling state: {e}") + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Error toggling: {e}", True) + return False + + def _calculate_indentation_level(self, line_text): + """Calculate the indentation level of a line.""" + if not line_text: + return 0 + + # Remove non-breaking spaces and convert to regular spaces + line = line_text.replace("\u00a0", " ") + + # Find the first non-whitespace character + match = re.search(r"[^ \t]", line) + if not match: + return 0 # Empty or whitespace-only line + + indent_text = line[:match.start()] + + # Calculate indentation level (4 spaces = 1 level, 1 tab = 1 level) + level = 0 + for char in indent_text: + if char == '\t': + level += 1 + elif char == ' ': + level += 0.25 # 4 spaces = 1 level + + return int(level) + + def _generate_indentation_tone(self, new_level, old_level): + """Generate an audio tone for indentation level change.""" + if not self._enabled: + return + + # Calculate frequency based on new indentation level + base_frequency = min( + self._base_frequency + (new_level * self._frequency_step), + self._max_frequency + ) + + # Add directional audio cues + if new_level > old_level: + # Indentation increased - higher pitch + frequency = base_frequency + 50 + elif new_level < old_level: + # Indentation decreased - lower pitch + frequency = max(base_frequency - 50, 100) + else: + # Same level (shouldn't happen but just in case) + frequency = base_frequency + + try: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: About to generate tone for level {new_level} (freq: {frequency}Hz)", True) + + if not SOUND_AVAILABLE or not self._player: + debug.printMessage(debug.LEVEL_INFO, "IndentationAudio: Sound player not available, using fallback", True) + # Fallback to ASCII bell + if new_level > 0: + beeps = min(new_level, 5) + for i in range(beeps): + print("\a", end="", flush=True) + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Sent {beeps} ASCII bell beeps", True) + return + + # Use Cthulhu's proper sound system + try: + # Create a tone based on indentation level + duration = self._tone_duration + volume_multiplier = 0.7 + + tone = Tone( + duration=duration, + frequency=frequency, + volumeMultiplier=volume_multiplier, + wave=Tone.SINE_WAVE + ) + + # Play the tone + self._player.play(tone, interrupt=False) + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Played Cthulhu tone - Level: {new_level}, Freq: {frequency}Hz", True) + + except Exception as sound_e: + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Cthulhu sound failed: {sound_e}", True) + # Fallback to ASCII bell + if new_level > 0: + beeps = min(new_level, 5) + for i in range(beeps): + print("\a", end="", flush=True) + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Used fallback ASCII bell ({beeps} beeps)", True) + + except Exception as e: + logger.error(f"IndentationAudio: Error generating tone: {e}") + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Exception in _generate_indentation_tone: {e}", True) + + def check_indentation_change(self, obj, line_text): + """Check if indentation has changed and play audio cue if needed. + + This method is intended to be called by scripts during line navigation. + """ + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: check_indentation_change called: enabled={self._enabled}, line='{line_text}'", True) + + if not self._enabled or not line_text: + return + + try: + # Get object identifier for tracking + obj_id = str(obj) if obj else "unknown" + + # Calculate current indentation level + current_level = self._calculate_indentation_level(line_text) + + # Get previous level for this object + previous_level = self._last_indentation_level.get(obj_id, current_level) + + # Update tracking + self._last_indentation_level[obj_id] = current_level + + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Levels - previous: {previous_level}, current: {current_level}", True) + + # Play audio cue if indentation changed + if current_level != previous_level: + self._generate_indentation_tone(current_level, previous_level) + + debug_msg = f"IndentationAudio: Indentation changed from {previous_level} to {current_level}" + debug.printMessage(debug.LEVEL_INFO, debug_msg, True) + + except Exception as e: + logger.error(f"IndentationAudio: Error checking indentation change: {e}") + debug.printMessage(debug.LEVEL_INFO, f"IndentationAudio: Exception in check_indentation_change: {e}", True) + + def is_enabled(self): + """Return whether the plugin is currently enabled.""" + return self._enabled + + def set_enabled(self, enabled): + """Set the enabled state of the plugin.""" + self._enabled = enabled + + def on_script_change(self, new_script): + """Handle when the active script changes.""" + try: + # Restore previous script if it was patched + self._restore_script_methods() + + # Re-apply patches to new script + self._monkey_patch_script_methods() + + # Clear tracking data for new context + self._last_indentation_level.clear() + + logger.info("IndentationAudio: Handled script change") + + except Exception as e: + logger.error(f"IndentationAudio: Error handling script change: {e}") \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/__init__.py new file mode 100644 index 0000000..a5dbd0a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/__init__.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""PluginManager plugin package.""" + +from .plugin import PluginManager + +__all__ = ['PluginManager'] \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.info new file mode 100644 index 0000000..115f79e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.info @@ -0,0 +1,8 @@ +name = PluginManager +version = 1.0.0 +description = GUI interface for managing Cthulhu plugins - enable/disable plugins with checkboxes +authors = Stormux +website = https://git.stormux.org/storm/cthulhu +copyright = Copyright 2025 +builtin = false +hidden = false \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.py new file mode 100644 index 0000000..78e4b24 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/PluginManager/plugin.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""PluginManager plugin for Cthulhu - GUI interface for managing plugins.""" + +import logging +import os +import configparser +from pathlib import Path + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, GLib + +from cthulhu.plugin import Plugin, cthulhu_hookimpl +from cthulhu import debug +from cthulhu import settings_manager + +logger = logging.getLogger(__name__) +_settingsManager = settings_manager.getManager() + + +class PluginManager(Plugin): + """Plugin that provides a GUI interface for managing other plugins.""" + + def __init__(self, *args, **kwargs): + """Initialize the PluginManager plugin.""" + super().__init__(*args, **kwargs) + self._kb_binding = None + self._dialog = None + self._plugin_checkboxes = {} + self._activated = False + + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Plugin initialized", True) + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the PluginManager plugin.""" + if plugin is not None and plugin is not self: + return + + # Prevent duplicate activation + if self._activated: + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Already activated, skipping", True) + return + + try: + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Plugin activation starting", True) + + # Register keybinding for opening plugin manager (Cthulhu+Shift+P) + self._register_keybinding() + + self._activated = True + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Plugin activated successfully", True) + return True + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: ERROR activating plugin: {e}", True) + return False + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the PluginManager plugin.""" + if plugin is not None and plugin is not self: + return + + try: + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Plugin deactivation starting", True) + + # Close dialog if open + if self._dialog: + self._dialog.destroy() + self._dialog = None + + self._activated = False + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Plugin deactivated successfully", True) + return True + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: ERROR deactivating plugin: {e}", True) + return False + + def _register_keybinding(self): + """Register the Cthulhu+Shift+P keybinding for opening plugin manager.""" + try: + if not self.app: + debug.printMessage(debug.LEVEL_INFO, "PluginManager: ERROR - No app reference available for keybinding", True) + return + + # Register Cthulhu+Shift+P keybinding + gesture_string = "kb:cthulhu+shift+p" + description = "Open plugin manager" + + self._kb_binding = self.registerGestureByString( + self._open_plugin_manager, + description, + gesture_string + ) + + if self._kb_binding: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Registered keybinding {gesture_string}", True) + else: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: ERROR - Failed to register keybinding {gesture_string}", True) + + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: ERROR registering keybinding: {e}", True) + + def _open_plugin_manager(self, script, inputEvent=None): + """Open the plugin manager dialog.""" + try: + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Opening plugin manager dialog", True) + + # Close existing dialog if open + if self._dialog: + self._dialog.destroy() + + # Create new dialog + self._create_dialog() + + return True + + except Exception as e: + logger.error(f"PluginManager: Error opening plugin manager: {e}") + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error opening dialog: {e}", True) + return False + + def _create_dialog(self): + """Create and show the plugin manager dialog.""" + try: + # Create dialog window + self._dialog = Gtk.Dialog( + title="Cthulhu Plugin Manager", + parent=None, + flags=Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT + ) + + # Set dialog properties + self._dialog.set_default_size(400, 300) + self._dialog.set_border_width(10) + + # Add buttons + self._dialog.add_button("Close", Gtk.ResponseType.CLOSE) + + # Create main content area + content_area = self._dialog.get_content_area() + + # Add title label + title_label = Gtk.Label() + title_label.set_markup("Available Plugins") + title_label.set_halign(Gtk.Align.CENTER) + content_area.pack_start(title_label, False, False, 10) + + # Add info label about PluginManager + info_label = Gtk.Label() + info_label.set_markup("Note:To apply changes, restart Cthulhu") + info_label.set_halign(Gtk.Align.CENTER) + content_area.pack_start(info_label, False, False, 5) + + # Create scrolled window for plugin list + scrolled = Gtk.ScrolledWindow() + scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + scrolled.set_size_request(-1, 200) + + # Create list box for plugins + self._plugin_listbox = Gtk.ListBox() + self._plugin_listbox.set_selection_mode(Gtk.SelectionMode.NONE) + scrolled.add(self._plugin_listbox) + + content_area.pack_start(scrolled, True, True, 0) + + # Populate plugin list + self._populate_plugin_list() + + # Connect signals + self._dialog.connect("response", self._on_dialog_response) + + # Show dialog + self._dialog.show_all() + + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Dialog created and shown", True) + + except Exception as e: + logger.error(f"PluginManager: Error creating dialog: {e}") + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error creating dialog: {e}", True) + + def _populate_plugin_list(self): + """Populate the plugin list with available plugins.""" + try: + # Get available plugins + available_plugins = self._discover_plugins() + + # Get currently active plugins + active_plugins = _settingsManager.getSetting('activePlugins') or [] + + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Found {len(available_plugins)} plugins", True) + + # Clear existing checkboxes + self._plugin_checkboxes.clear() + + # Add each plugin as a checkbox (except PluginManager itself) + for plugin_name, plugin_info in sorted(available_plugins.items()): + # Skip PluginManager to prevent users from disabling plugin management + if plugin_name == "PluginManager": + continue + + # Create row container + row = Gtk.ListBoxRow() + row.set_activatable(False) + + # Create horizontal box for checkbox and info + hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) + hbox.set_border_width(5) + + # Create checkbox + checkbox = Gtk.CheckButton() + checkbox.set_active(plugin_name in active_plugins) + checkbox.connect("toggled", self._on_plugin_toggled, plugin_name) + + # Create plugin info label + info_text = f"{plugin_name}" + if plugin_info.get('description'): + info_text += f"\n{plugin_info['description']}" + if plugin_info.get('version'): + info_text += f" (v{plugin_info['version']})" + + label = Gtk.Label() + label.set_markup(info_text) + label.set_halign(Gtk.Align.START) + label.set_line_wrap(True) + + # Pack widgets + hbox.pack_start(checkbox, False, False, 0) + hbox.pack_start(label, True, True, 0) + + row.add(hbox) + self._plugin_listbox.add(row) + + # Store checkbox reference + self._plugin_checkboxes[plugin_name] = checkbox + + except Exception as e: + logger.error(f"PluginManager: Error populating plugin list: {e}") + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error populating list: {e}", True) + + def _discover_plugins(self): + """Discover all available plugins.""" + plugins = {} + + try: + # Get plugin system manager + from cthulhu import plugin_system_manager + + # Use existing plugin manager to get plugins + if hasattr(plugin_system_manager, '_manager') and plugin_system_manager._manager: + manager = plugin_system_manager._manager + manager.rescanPlugins() + + for plugin_info in manager.plugins: + plugin_name = plugin_info.get_module_name() + plugins[plugin_name] = { + 'name': plugin_name, + 'description': getattr(plugin_info, 'description', ''), + 'version': getattr(plugin_info, 'version', ''), + 'path': getattr(plugin_info, 'module_dir', '') + } + else: + # Fallback: manually scan plugin directories + plugins = self._manual_plugin_discovery() + + except Exception as e: + logger.error(f"PluginManager: Error in plugin discovery: {e}") + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Plugin discovery error: {e}", True) + # Fallback to manual discovery + plugins = self._manual_plugin_discovery() + + return plugins + + def _manual_plugin_discovery(self): + """Manually discover plugins by scanning directories.""" + plugins = {} + + try: + # Get plugin directories + from cthulhu.plugin_system_manager import PluginType + + system_dir = PluginType.SYSTEM.get_root_dir() + user_dir = PluginType.USER.get_root_dir() + + for plugin_dir in [system_dir, user_dir]: + if os.path.exists(plugin_dir): + self._scan_plugin_directory(plugin_dir, plugins) + + except Exception as e: + logger.error(f"PluginManager: Error in manual discovery: {e}") + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Manual discovery error: {e}", True) + + return plugins + + def _scan_plugin_directory(self, directory, plugins): + """Scan a directory for plugins.""" + try: + for item in os.listdir(directory): + plugin_path = os.path.join(directory, item) + if os.path.isdir(plugin_path): + # Check for plugin.py and plugin.info + plugin_py = os.path.join(plugin_path, "plugin.py") + plugin_info_file = os.path.join(plugin_path, "plugin.info") + + if os.path.exists(plugin_py): + plugin_info = {'name': item, 'description': '', 'version': ''} + + # Try to read plugin.info + if os.path.exists(plugin_info_file): + try: + config = configparser.ConfigParser() + config.read(plugin_info_file) + + # Handle both INI-style and simple key=value format + if config.sections(): + # INI-style format + for section in config.sections(): + for key, value in config[section].items(): + if key.lower() in ['description', 'version']: + plugin_info[key.lower()] = value + else: + # Simple key=value format + with open(plugin_info_file, 'r') as f: + for line in f: + line = line.strip() + if '=' in line and not line.startswith('#'): + key, value = line.split('=', 1) + key = key.strip().lower() + value = value.strip() + if key in ['description', 'version']: + plugin_info[key] = value + except Exception as info_e: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error reading {plugin_info_file}: {info_e}", True) + + plugins[item] = plugin_info + + except Exception as e: + logger.error(f"PluginManager: Error scanning directory {directory}: {e}") + + def _on_plugin_toggled(self, checkbox, plugin_name): + """Handle plugin checkbox toggle.""" + try: + is_active = checkbox.get_active() + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Plugin {plugin_name} toggled to {'active' if is_active else 'inactive'}", True) + + # Get current active plugins + active_plugins = _settingsManager.getSetting('activePlugins') or [] + active_plugins = list(active_plugins) # Make a copy + + # Update the list + if is_active and plugin_name not in active_plugins: + active_plugins.append(plugin_name) + elif not is_active and plugin_name in active_plugins: + active_plugins.remove(plugin_name) + + # Save updated settings + _settingsManager.setSetting('activePlugins', active_plugins) + + # Save to disk using the backend directly + try: + # Get current general settings + current_general = _settingsManager.getGeneralSettings() + current_general['activePlugins'] = active_plugins + + # Save using the backend + backend = _settingsManager._backend + if backend: + backend.saveDefaultSettings( + current_general, + _settingsManager.getPronunciations(), + _settingsManager.getKeybindings() + ) + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Settings saved to backend", True) + else: + debug.printMessage(debug.LEVEL_INFO, "PluginManager: No backend available for saving", True) + + except Exception as save_e: + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error saving via backend: {save_e}", True) + + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Updated active plugins: {active_plugins}", True) + + except Exception as e: + logger.error(f"PluginManager: Error toggling plugin {plugin_name}: {e}") + debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error toggling {plugin_name}: {e}", True) + + + def _on_dialog_response(self, dialog, response_id): + """Handle dialog response (close button clicked).""" + try: + if response_id == Gtk.ResponseType.CLOSE: + dialog.destroy() + self._dialog = None + debug.printMessage(debug.LEVEL_INFO, "PluginManager: Dialog closed", True) + + except Exception as e: + logger.error(f"PluginManager: Error handling dialog response: {e}") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.info new file mode 100644 index 0000000..cd4aad3 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.info @@ -0,0 +1,9 @@ +[Plugin] +Name = Simple Plugin System +Module = SimplePluginSystem +Description = Simple plugin system implementation for Cthulhu +Authors = Storm Dragon +Copyright = Copyright (c) 2025 Stormux +Website = https://git.stormux.org/storm/cthulhu +Version = 1.0 +Category = System diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.py new file mode 100644 index 0000000..95948ea --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/SimplePluginSystem/plugin.py @@ -0,0 +1,407 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# +# 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. +# + +"""Simple Plugin System for Cthulhu.""" + +import glob +import os +import importlib.util +import random +import string +import _thread +import logging +from subprocess import Popen, PIPE +import gettext + +from cthulhu.plugin import Plugin, cthulhu_hookimpl + +# Set up translation function +_ = gettext.gettext + +logger = logging.getLogger(__name__) + +# Global variables for API access +settings = None +speech = None +braille = None +input_event = None + +def outputMessage(Message): + """Output a message via speech and/or braille depending on settings.""" + if (settings.enableSpeech): + speech.speak(Message) + if (settings.enableBraille): + braille.displayMessage(Message) + +class SimplePluginSystem(Plugin): + """Simple plugin system implementation for Cthulhu. + + This plugin allows loading and managing simple script-based plugins + from a designated directory. + """ + + def __init__(self, *args, **kwargs): + """Initialize the plugin system.""" + super().__init__(*args, **kwargs) + logger.info("SimplePluginSystem plugin initialized") + self.plugin_list = [] + self.loaded = False + self.plugin_repo = os.path.expanduser('~') + "/.local/share/cthulhu/simple-plugins-enabled/" + self._signal_handler_id = None + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin system.""" + # Skip if this activation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Activating SimplePluginSystem plugin") + try: + global settings + global speech + global braille + global input_event + + settings = self.app.getDynamicApiManager().getAPI('Settings') + speech = self.app.getDynamicApiManager().getAPI('Speech') + braille = self.app.getDynamicApiManager().getAPI('Braille') + input_event = self.app.getDynamicApiManager().getAPI('InputEvent') + + if not self.loaded: + self.load_plugins() + + except Exception as e: + logger.error(f"Error activating SimplePluginSystem plugin: {e}") + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin system.""" + # Skip if this deactivation call isn't for us + if plugin is not None and plugin is not self: + return + + logger.info("Deactivating SimplePluginSystem plugin") + try: + # Remove all registered keybindings + for plugin in self.plugin_list: + self.unregisterShortcut(plugin['function'], plugin['shortcut']) + self.loaded = False + self.plugin_list = [] + except Exception as e: + logger.error(f"Error deactivating SimplePluginSystem plugin: {e}") + + def SetupShortcutAndHandle(self, currPluginSetting): + """Set up keyboard shortcuts for a plugin.""" + shortcut = '' + # just the modifier + if not currPluginSetting['shiftkey'] and not currPluginSetting['ctrlkey'] and not currPluginSetting['altkey']: + shortcut = 'kb:cthulhu+' + currPluginSetting['key'] + # cthulhu + alt + if not currPluginSetting['shiftkey'] and not currPluginSetting['ctrlkey'] and currPluginSetting['altkey']: + shortcut = 'kb:cthulhu+alt+' + currPluginSetting['key'] + # cthulhu + CTRL + if not currPluginSetting['shiftkey'] and currPluginSetting['ctrlkey'] and not currPluginSetting['altkey']: + shortcut = 'kb:cthulhu+control+' + currPluginSetting['key'] + # cthulhu + alt + CTRL + if not currPluginSetting['shiftkey'] and currPluginSetting['ctrlkey'] and currPluginSetting['altkey']: + shortcut = 'kb:cthulhu+alt+control+ ' + currPluginSetting['key'] + # cthulhu + shift + if currPluginSetting['shiftkey'] and not currPluginSetting['ctrlkey'] and not currPluginSetting['altkey']: + shortcut = 'kb:cthulhu+shift+' + currPluginSetting['key'] + # alt + shift + if currPluginSetting['shiftkey'] and not currPluginSetting['ctrlkey'] and currPluginSetting['altkey']: + shortcut = 'kb:alt+shift+' + currPluginSetting['key'] + if shortcut != '': + logger.debug(f"Registering shortcut: {shortcut}") + currPluginSetting['shortcut'] = shortcut + try: + # Try to use the translation function, fall back to plain text if it fails + plugin_name = _(currPluginSetting['pluginname']) + except Exception: + # If translation fails, use the original name + plugin_name = currPluginSetting['pluginname'] + logger.warning(f"Translation failed for plugin: {currPluginSetting['pluginname']}") + + self.registerGestureByString(currPluginSetting['function'], plugin_name, shortcut) + return currPluginSetting + + def id_generator(self, size=7, chars=string.ascii_letters): + """Generate a random ID string.""" + return ''.join(random.choice(chars) for _ in range(size)) + + def initSettings(self): + """Initialize default settings for a plugin.""" + currPluginSetting = { + 'pluginname': '', + 'functionname': '', + 'key': '', + 'shiftkey': False, + 'ctrlkey': False, + 'altkey': False, + 'startnotify': False, + 'stopnotify': False, + 'blockcall': False, + 'error': False, + 'exec': False, + 'parameters': '', + 'function': None, + 'inputeventhandler': None, + 'valid': False, + 'supressoutput': False, + 'shortcut': '' + } + return currPluginSetting + + def getPluginSettings(self, filepath, currPluginSetting): + """Parse plugin settings from filename and content.""" + try: + currPluginSetting['file'] = filepath + fileName, fileExtension = os.path.splitext(filepath) + if (fileExtension and (fileExtension != '')): # if there is an extension + currPluginSetting['loadable'] = (fileExtension.lower() == '.py') # only python is loadable + filename = os.path.basename(filepath) # filename + filename = os.path.splitext(filename)[0] # remove extension if we have one + # remove pluginname seperated by __-__ + filenamehelper = filename.split('__-__') + filename = filenamehelper[len(filenamehelper) - 1] + currPluginSetting['permission'] = os.access(filepath, os.X_OK) + currPluginSetting['pluginname'] = 'NoNameAvailable' + if len(filenamehelper) == 2: + currPluginSetting['pluginname'] = filenamehelper[0] + # now get shortcuts seperated by __+__ + filenamehelper = filename.split('__+__') + if len([y for y in filenamehelper if 'parameters_' in y.lower()]) == 1 and\ + len([y for y in filenamehelper if 'parameters_' in y.lower()][0]) > 11: + currPluginSetting['parameters'] = [y for y in filenamehelper if 'parameters_' in y.lower()][0][11:] + if len([y for y in filenamehelper if 'key_' in y.lower()]) == 1 and\ + len([y for y in filenamehelper if 'key_' in y.lower()][0]) > 4: + currPluginSetting['key'] = [y for y in filenamehelper if 'key_' in y.lower()][0][4] + if currPluginSetting['key'] == '': + settcurrPluginSetting = 'shift' in map(str.lower, filenamehelper) + currPluginSetting['ctrlkey'] = 'control' in map(str.lower, filenamehelper) + currPluginSetting['altkey'] = 'alt' in map(str.lower, filenamehelper) + currPluginSetting['startnotify'] = 'startnotify' in map(str.lower, filenamehelper) + currPluginSetting['stopnotify'] = 'stopnotify' in map(str.lower, filenamehelper) + currPluginSetting['blockcall'] = 'blockcall' in map(str.lower, filenamehelper) + currPluginSetting['error'] = 'error' in map(str.lower, filenamehelper) + currPluginSetting['supressoutput'] = 'supressoutput' in map(str.lower, filenamehelper) + currPluginSetting['exec'] = 'exec' in map(str.lower, filenamehelper) + currPluginSetting['loadmodule'] = 'loadmodule' in map(str.lower, filenamehelper) + currPluginSetting = self.readSettingsFromPlugin(currPluginSetting) + if not currPluginSetting['loadmodule']: + if not currPluginSetting['permission']: # subprocessing only works with exec permission + return self.initSettings() + if currPluginSetting['loadmodule'] and not currPluginSetting['loadable']: # sorry.. its not loadable only .py is loadable + return self.initSettings() + if (len(currPluginSetting['key']) > 1): # no shortcut + if not currPluginSetting['exec']: # and no exec -> the plugin make no sense because it isnt hooked anywhere + return self.initSettings() # so not load it (sets valid = False) + else: + currPluginSetting['key'] = '' # there is a strange key, but exec? ignore the key.. + currPluginSetting['valid'] = True # we could load everything + return currPluginSetting + except Exception as e: + logger.error(f"Error getting plugin settings: {e}") + return self.initSettings() + + def readSettingsFromPlugin(self, currPluginSetting): + """Read settings from plugin file content.""" + if not os.access(currPluginSetting['file'], os.R_OK): + return currPluginSetting + fileName, fileExtension = os.path.splitext(currPluginSetting['file']) + if (fileExtension and (fileExtension != '')): # if there is an extension + if (fileExtension.lower() != '.py') and \ + (fileExtension.lower() != '.sh'): + return currPluginSetting + else: + return currPluginSetting + + try: + with open(currPluginSetting['file'], "r") as pluginFile: + for line in pluginFile: + currPluginSetting['shiftkey'] = ('sopsproperty:shift' in line.lower().replace(" ", "")) or currPluginSetting['shiftkey'] + currPluginSetting['ctrlkey'] = ('sopsproperty:control' in line.lower().replace(" ", "")) or currPluginSetting['ctrlkey'] + currPluginSetting['altkey'] = ('sopsproperty:alt' in line.lower().replace(" ", "")) or currPluginSetting['altkey'] + currPluginSetting['startnotify'] = ('sopsproperty:startnotify' in line.lower().replace(" ", "")) or currPluginSetting['startnotify'] + currPluginSetting['stopnotify'] = ('sopsproperty:stopnotify' in line.lower().replace(" ", "")) or currPluginSetting['stopnotify'] + currPluginSetting['blockcall'] = ('sopsproperty:blockcall' in line.lower().replace(" ", "")) or currPluginSetting['blockcall'] + currPluginSetting['error'] = ('sopsproperty:error' in line.lower().replace(" ", "")) or currPluginSetting['error'] + currPluginSetting['supressoutput'] = ('sopsproperty:supressoutput' in line.lower().replace(" ", "")) or currPluginSetting['supressoutput'] + currPluginSetting['exec'] = ('sopsproperty:exec' in line.lower().replace(" ", "")) or currPluginSetting['exec'] + currPluginSetting['loadmodule'] = ('sopsproperty:loadmodule' in line.lower().replace(" ", "")) or currPluginSetting['loadmodule'] + except Exception as e: + logger.error(f"Error reading plugin file: {e}") + + return currPluginSetting + + def buildPluginSubprocess(self, currPluginSetting): + """Build a function to execute a plugin as a subprocess.""" + currplugin = "\'\"" + currPluginSetting['file'] + "\" " + currPluginSetting['parameters'] + "\'" + pluginname = currPluginSetting['pluginname'] + if currPluginSetting['blockcall']: + pluginname = "blocking " + pluginname + fun_body = "global " + currPluginSetting['functionname'] + "\n" + fun_body += "def " + currPluginSetting['functionname'] + "(script=None, inputEvent=None):\n" + if currPluginSetting['startnotify']: + fun_body += " outputMessage('start " + pluginname + "')\n" + fun_body += " p = Popen(" + currplugin + ", stdout=PIPE, stderr=PIPE, shell=True)\n" + fun_body += " stdout, stderr = p.communicate()\n" + fun_body += " message = ''\n" + fun_body += " if not " + str(currPluginSetting['supressoutput']) + " and stdout:\n" + fun_body += " message += str(stdout, \"utf-8\")\n" + fun_body += " if " + str(currPluginSetting['error']) + " and stderr:\n" + fun_body += " message += ' error: ' + str(stderr, \"utf-8\")\n" + fun_body += " outputMessage(message)\n" + if currPluginSetting['stopnotify']: + fun_body += " outputMessage('finish " + pluginname + "')\n" + fun_body += " return True\n\n" + fun_body += "global " + currPluginSetting['functionname'] + "T\n" + fun_body += "def " + currPluginSetting['functionname'] + "T(script=None, inputEvent=None):\n" + fun_body += " _thread.start_new_thread(" + currPluginSetting['functionname'] + ",(script, inputEvent))\n\n" + return fun_body + + def buildPluginExec(self, currPluginSetting): + """Build a function to execute a plugin as a Python module.""" + pluginname = currPluginSetting['pluginname'] + if currPluginSetting['blockcall']: + pluginname = "blocking " + pluginname + fun_body = "global " + currPluginSetting['functionname'] + "\n" + fun_body += "def " + currPluginSetting['functionname'] + "(script=None, inputEvent=None):\n" + if currPluginSetting['startnotify']: + fun_body += " outputMessage('start " + pluginname + "')\n" + fun_body += " try:\n" + fun_body += " spec = importlib.util.spec_from_file_location(\"" + currPluginSetting['functionname'] + "\",\"" + currPluginSetting['file'] + "\")\n" + fun_body += " " + currPluginSetting['functionname'] + "Module = importlib.util.module_from_spec(spec)\n" + fun_body += " spec.loader.exec_module(" + currPluginSetting['functionname'] + "Module)\n" + fun_body += " except Exception as e:\n" + fun_body += " logger.error(f\"Error executing plugin {pluginname}: {e}\")\n" + if currPluginSetting['error']: + fun_body += " outputMessage(\"Error while executing " + pluginname + "\")\n" + if currPluginSetting['stopnotify']: + fun_body += " outputMessage('finish " + pluginname + "')\n" + fun_body += " return True\n\n" + fun_body += "global " + currPluginSetting['functionname'] + "T\n" + fun_body += "def " + currPluginSetting['functionname'] + "T(script=None, inputEvent=None):\n" + fun_body += " _thread.start_new_thread(" + currPluginSetting['functionname'] + ",(script, inputEvent))\n\n" + return fun_body + + def getFunctionName(self, currPluginSetting): + """Generate a unique function name for a plugin.""" + currPluginSetting['functionname'] = '' + while currPluginSetting['functionname'] == '' or currPluginSetting['functionname'] + 'T' in globals() or currPluginSetting['functionname'] in globals(): + currPluginSetting['functionname'] = self.id_generator() + return currPluginSetting + + def registerGestureByString(self, function, description, shortcut): + """Register a keyboard shortcut for a function. + + This is a compatibility wrapper for the new plugin system. + """ + try: + if self.app: + api_helper = self.app.getAPIHelper() + if api_helper: + api_helper.registerGestureByString( + function, + description, + shortcut, + 'default', + 'cthulhu', + True, + contextName=self.module_name + ) + logger.debug(f"Registered shortcut {shortcut} for {description}") + return True + else: + logger.error("Could not get APIHelper") + else: + logger.error("No app reference available") + except Exception as e: + logger.error(f"Error registering shortcut {shortcut}: {e}") + + def unregisterShortcut(self, function, shortcut): + """Unregister a keyboard shortcut for a function. + + This is a compatibility wrapper for the new plugin system. + """ + try: + if self.app: + api_helper = self.app.getAPIHelper() + if api_helper and hasattr(api_helper, 'unregisterShortcut'): + api_helper.unregisterShortcut(shortcut) + logger.debug(f"Unregistered shortcut {shortcut}") + return True + else: + logger.error("Could not get APIHelper or unregisterShortcut method") + else: + logger.error("No app reference available") + except Exception as e: + logger.error(f"Error unregistering shortcut {shortcut}: {e}") + + def load_plugins(self): + """Load and setup all plugins in the plugin repository.""" + if not self.loaded: + try: + logger.info(f"Loading plugins from {self.plugin_repo}") + plugin_files = glob.glob(self.plugin_repo + '*') + self.plugin_list = [] # Reset the plugin list to avoid confusion + + for currplugin in plugin_files: + try: + # Ensure currplugin is a valid path string + if not isinstance(currplugin, (str, bytes, os.PathLike)): + logger.error(f"Invalid plugin path: {type(currplugin)}") + continue + + currPluginSetting = self.initSettings() + currPluginSetting = self.getPluginSettings(currplugin, currPluginSetting) + + if not currPluginSetting['valid']: + logger.debug(f"Skipping invalid plugin: {currplugin}") + continue + + currPluginSetting = self.getFunctionName(currPluginSetting) + + if currPluginSetting['loadmodule']: + exec(self.buildPluginExec(currPluginSetting)) # load as python module + else: + exec(self.buildPluginSubprocess(currPluginSetting)) # run as subprocess + + if currPluginSetting['blockcall']: + currPluginSetting['function'] = globals()[currPluginSetting['functionname']] # non threaded + else: + currPluginSetting['function'] = globals()[currPluginSetting['functionname'] + "T"] # T = Threaded + + if currPluginSetting['exec']: # exec on load if we want + currPluginSetting['function']() + + if not currPluginSetting['key'] == '': + currPluginSetting = self.SetupShortcutAndHandle(currPluginSetting) + + logger.debug(f"Loaded plugin: {currPluginSetting['pluginname']}") + self.plugin_list.append(currPluginSetting) # store in a list + except Exception as e: + logger.error(f"Error loading plugin {currplugin}: {e}") + + self.loaded = True + logger.info(f"Loaded {len(self.plugin_list)} plugins") + except Exception as e: + logger.error(f"Error in load_plugins: {e}") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.info new file mode 100644 index 0000000..50e52cc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.info @@ -0,0 +1,8 @@ +name = Hello World +version = 1.0.0 +description = Test plugin for Cthulhu +authors = Storm Dragon storm_dragon@stormux.org +website = https://stormux.org +copyright = Copyright 2025 +builtin = false +hidden = false diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.py new file mode 100644 index 0000000..0876922 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/hello_world/plugin.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2025 Stormux +# +# 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. + +"""Hello World plugin for Cthulhu.""" + +import logging +from cthulhu.plugin import Plugin, cthulhu_hookimpl + +logger = logging.getLogger(__name__) + +class HelloWorld(Plugin): + """Hello World plugin.""" + + def __init__(self, *args, **kwargs): + """Initialize the plugin.""" + super().__init__(*args, **kwargs) + print("Plugin hello world initialized.") + logger.info("HelloWorld plugin initialized") + + @cthulhu_hookimpl + def activate(self, plugin=None): + """Activate the plugin.""" + # Skip if this activation call isn't for us + if plugin is not None and plugin is not self: + return + + try: + logger.info("Activating Hello World plugin") + + # Register our keyboard shortcut + self.registerGestureByString( + self.speakTest, + "hello world", + "kb:cthulhu+z", + learnModeEnabled=True + ) + except Exception as e: + logger.error(f"Error activating Hello World plugin: {e}") + + @cthulhu_hookimpl + def deactivate(self, plugin=None): + """Deactivate the plugin.""" + # Skip if this deactivation call isn't for us + if plugin is not None and plugin is not self: + return + + try: + logger.info("Deactivating Hello World plugin") + except Exception as e: + logger.error(f"Error deactivating Hello World plugin: {e}") + + def speakTest(self, script=None, inputEvent=None): + """Speak a test message.""" + try: + if self.app: + self.app.getDynamicApiManager().getAPI('CthulhuState').activeScript.presentMessage( + 'hello world', + resetStyles=False + ) + + return True + except Exception as e: + logger.error(f"Error in speakTest: {e}") + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.info b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.info new file mode 100644 index 0000000..9ebe67d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.info @@ -0,0 +1,12 @@ +[Plugin] +name=Self Voice +module_name=self_voice +version=1.0.0 +description=Use Cthulhu speech and braille from external applications via Unix sockets +authors=Stormux +copyright=Copyright (c) 2024 Stormux +website=https://stormux.org +icon_name=audio-speakers +builtin=false +hidden=false +help_uri=https://stormux.org diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.py new file mode 100644 index 0000000..5a52d55 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/plugins/self_voice/plugin.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# +# 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. +# + +"""Self Voice plugin for Cthulhu screen reader.""" + +import os +import socket +import select +import logging +import threading +from threading import Thread, Lock +from cthulhu.plugin import Plugin, cthulhu_hookimpl + +logger = logging.getLogger(__name__) + +# Special codes for message handling +APPEND_CODE = '<#APPEND#>' +PERSISTENT_CODE = '<#PERSISTENT#>' + +class SelfVoice(Plugin): + """Plugin that provides a socket interface for external applications to send text to Cthulhu.""" + + def __init__(self): + """Initialize the plugin.""" + super().__init__() + self.lock = Lock() + self.active = False + self.voiceThread = Thread(target=self.voiceWorker) + self.voiceThread.daemon = True # Make thread exit when main thread exits + + @cthulhu_hookimpl + def activate(self): + """Activate the self-voice plugin.""" + super().activate() + logger.info("Activating Self Voice Plugin") + self.activateWorker() + + @cthulhu_hookimpl + def deactivate(self): + """Deactivate the self-voice plugin.""" + logger.info("Deactivating Self Voice Plugin") + self.deactivateWorker() + super().deactivate() + + def activateWorker(self): + """Start the voice worker thread.""" + with self.lock: + self.active = True + + # Only start if not already running + if not self.voiceThread.is_alive(): + self.voiceThread = Thread(target=self.voiceWorker) + self.voiceThread.daemon = True + self.voiceThread.start() + + def deactivateWorker(self): + """Stop the voice worker thread.""" + with self.lock: + self.active = False + + # Try to join the thread if it's alive, with a timeout + if self.voiceThread.is_alive(): + try: + self.voiceThread.join(timeout=2.0) + except Exception as e: + logger.warning(f"Error stopping voice worker thread: {e}") + + def isActive(self): + """Check if the worker is active.""" + with self.lock: + return self.active + + def outputMessage(self, message): + """Output a message through Cthulhu's speech and braille systems. + + Args: + message: The message to output. May include special codes. + """ + # Process special codes + append = message.startswith(APPEND_CODE) + if append: + message = message[len(APPEND_CODE):] + + persistent = False + if message.endswith(PERSISTENT_CODE): + message = message[:len(message)-len(PERSISTENT_CODE)] + persistent = True + + # Output through appropriate channel + if persistent: + # Use the APIHelper for persistent messages + self.app.getAPIHelper().outputMessage(message, not append) + else: + # Use the script manager for standard messages + script_manager = self.app.getDynamicApiManager().getAPI('ScriptManager') + scriptManager = script_manager.getManager() + scriptManager.getDefaultScript().presentMessage(message, resetStyles=False) + + def voiceWorker(self): + """Worker thread that listens on a socket for messages to speak.""" + socketFile = '/tmp/cthulhu.sock' + # For testing purposes + # socketFile = '/tmp/cthulhu-plugin.sock' + + # Clean up any existing socket file + if os.path.exists(socketFile): + try: + os.unlink(socketFile) + except Exception as e: + logger.error(f"Error removing existing socket file: {e}") + return + + try: + # Create and set up the socket + cthulhu_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + cthulhu_sock.bind(socketFile) + os.chmod(socketFile, 0o222) # Write-only for everyone + cthulhu_sock.listen(1) + + logger.info(f"Self Voice plugin listening on {socketFile}") + + # Main loop - listen for connections + while self.isActive(): + # Check if data is available with a timeout + try: + r, _, _ = select.select([cthulhu_sock], [], [], 0.8) + except select.error as e: + logger.error(f"Select error: {e}") + break + + if not r: # No data available + continue + + # Accept connection + if cthulhu_sock in r: + try: + client_sock, _ = cthulhu_sock.accept() + client_sock.settimeout(0.5) # Set a timeout for receiving data + + try: + # Receive and process data + raw_data = client_sock.recv(8192) + if raw_data: + data = raw_data.decode("utf-8").strip() + if data: + self.outputMessage(data) + except socket.timeout: + pass + except Exception as e: + logger.error(f"Error receiving data: {e}") + finally: + client_sock.close() + except Exception as e: + logger.error(f"Error accepting connection: {e}") + + except Exception as e: + logger.error(f"Socket error: {e}") + finally: + # Clean up + if 'cthulhu_sock' in locals(): + try: + cthulhu_sock.close() + except Exception: + pass + + if os.path.exists(socketFile): + try: + os.unlink(socketFile) + except Exception as e: + logger.error(f"Error removing socket file: {e}") + + logger.info("Self Voice plugin socket closed") diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/pronunciation_dict.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/pronunciation_dict.py new file mode 100644 index 0000000..b199a44 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/pronunciation_dict.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Exposes a dictionary, pronunciation_dict, that maps words to what +they sound like.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +def getPronunciation(word, pronunciations=None): + """Given a word, return a string that represents what this word + sounds like. Note: This code does not handle the pronunciation + of character names. If you want a character name to be spoken, + treat it as a punctuation character at LEVEL_NONE in + punctuation_settings.py. See, for example, the left_arrow and + right_arrow characters. + + Arguments: + - word: the word to get the "sounds like" representation for. + - pronunciations: an optional dictionary used to get the pronunciation + from. + + Returns a string that represents what this word sounds like, or + the word if there is no representation. + """ + + lowerWord = word.lower() + dictionary = pronunciations or pronunciation_dict + entry = dictionary.get(lowerWord, [word, word]) + + return entry[1] + +def setPronunciation(word, replacementString, pronunciations=None): + """Given an actual word, and a replacement string, set a key/value + pair in a pronunciation dictionary. + + Arguments: + - word: the word to be pronunced. + - replacementString: the replacement string to use instead. + - pronunciations: an optional dictionary used to set the pronunciation + into. + """ + + key = word.lower() + if pronunciations is not None: + pronunciations[key] = [ word, replacementString ] + else: + pronunciation_dict[key] = [ word, replacementString ] + +# pronunciation_dict is a dictionary where the keys are words and the +# values represent word the pronunciation of that word (in other words, +# what the word sounds like). +# +pronunciation_dict = {} diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/punctuation_settings.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/punctuation_settings.py new file mode 100644 index 0000000..4f6ee32 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/punctuation_settings.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Punctuation Verbosity settings. +The Cthulhu punctuation settings are broken up into 4 modes. + +These modes are None, Some, Most and All. + +They are defined by a group of radio buttons on the speech +page of the configuration user interface. + +Each mode is defined below. The 4 bits of information listed here are: + + - The actual printed symbol. + + - How the symbol should be pronounced (in the chnames dictionary in + chnames.py keyed by symbol). + + - The level at which the symbol should be spoken. Note that this + denotes the level containing all lower levels. + + - Whether or not the spoken name for the symbol should replace the + actual symbol or be inserted before the symbol. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +from . import settings + +# Whether or not the spoken name for the symbol should replace the +# actual symbol or be inserted before the symbol. +# +PUNCTUATION_REPLACE = 0 +PUNCTUATION_INSERT = 1 + +# The lowest level at which the spoken name should be spoken. Thus a symbol +# with a level of LEVEL_MOST will be spoken at LEVEL_MOST and LEVEL_ALL. +# +LEVEL_ALL = settings.PUNCTUATION_STYLE_ALL +LEVEL_MOST = settings.PUNCTUATION_STYLE_MOST +LEVEL_SOME = settings.PUNCTUATION_STYLE_SOME +LEVEL_NONE = settings.PUNCTUATION_STYLE_NONE + +# Bullets and bullet-like characters +# +middle_dot = '\u00b7' +bullet = '\u2022' +triangular_bullet = '\u2023' +hyphen_bullet = '\u2043' +black_square = '\u25a0' +white_square = '\u25a1' +white_bullet = '\u25e6' +white_circle = '\u25cb' +black_diamond = '\u25c6' +black_circle = '\u25cf' +check_mark = '\u2713' +heavy_check_mark = '\u2714' +x_shaped_bullet = '\u2717' +heavy_right_arrow = '\u2794' +right_arrowhead = '\u27a2' + +# StarOffice/OOo's special-purpose bullet chararacters +# +SO_black_square = '\ue00a' +SO_black_diamond = '\ue00c' + +# Miscellaneous other symbols +# +cent = '\u00a2' +pound = '\u00a3' +yen = '\u00a5' +section = '\u00a7' +copyright_sign = '\u00a9' +left_double_angle = '\u00ab' +not_sign = '\u00ac' +registered = '\u00ae' +degree = '\u00b0' +plus_minus = '\u00b1' +right_double_angle = '\u00bb' +one_quarter = '\u00bc' +one_half = '\u00bd' +three_quarters = '\u00be' +multiply = '\u00d7' +divide = '\u00f7' +en_dash = '\u2013' +left_single_quote = '\u2018' +right_single_quote = '\u2019' +single_low_quote = '\u201a' +left_double_quote = '\u201c' +right_double_quote = '\u201d' +double_low_quote = '\u201e' +dagger = '\u2020' +double_dagger = '\u2021' +per_mille = '\u2030' +prime = '\u2032' +double_prime = '\u2033' +euro = '\u20ac' +trademark = '\u2122' +left_arrow = '\u2190' +right_arrow = '\u2192' +infinity = '\u221e' +almost_equal = '\u2248' +not_equal = '\u2260' +lt_or_equal = '\u2264' +gt_or_equal = '\u2265' +square_root = '\u221a' +cube_root = '\u221b' + +superscript_zero = '\u2070' +superscript1 = '\u00b9' +superscript2 = '\u00b2' +superscript3 = '\u00b3' +superscript4 = '\u2074' +superscript5 = '\u2075' +superscript6 = '\u2076' +superscript7 = '\u2077' +superscript8 = '\u2078' +superscript9 = '\u2079' +superscript_plus = '\u207a' +superscript_minus = '\u207b' +superscript_equals = '\u207c' +superscript_left_paren = '\u207d' +superscript_right_paren = '\u207e' +superscriptn = '\u207f' +subscript_zero = '\u2080' +subscript1 = '\u2081' +subscript2 = '\u2082' +subscript3 = '\u2083' +subscript4 = '\u2084' +subscript5 = '\u2085' +subscript6 = '\u2086' +subscript7 = '\u2087' +subscript8 = '\u2088' +subscript9 = '\u2089' +subscript_plus = '\u208a' +subscript_minus = '\u208b' +subscript_equals = '\u208c' +subscript_left_paren = '\u208d' +subscript_right_paren = '\u208e' + +# punctuation is a dictionary where the keys represent a unicode +# character and the values are a list of two elements where the +# first represents the punctuation style and the second represents +# the action to take. +# +punctuation = {} + +punctuation["!"] = [ LEVEL_ALL, PUNCTUATION_INSERT ] +punctuation["'"] = [ LEVEL_ALL, PUNCTUATION_REPLACE ] +punctuation[","] = [ LEVEL_ALL, PUNCTUATION_INSERT ] +punctuation["."] = [ LEVEL_ALL, PUNCTUATION_INSERT ] +punctuation["?"] = [ LEVEL_ALL, PUNCTUATION_INSERT ] +punctuation[right_single_quote] = [ LEVEL_ALL, PUNCTUATION_REPLACE ] + +punctuation["\""] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["("] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[")"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["-"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["_"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[":"] = [ LEVEL_MOST, PUNCTUATION_INSERT ] +punctuation[";"] = [ LEVEL_MOST, PUNCTUATION_INSERT ] +punctuation["<"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[">"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["["] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["]"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["\\"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["|"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["`"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["~"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["{"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["}"] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[left_single_quote] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[left_double_quote] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[right_double_quote] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[en_dash] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[double_low_quote] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[single_low_quote] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[left_double_angle] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation[right_double_angle] = [ LEVEL_MOST, PUNCTUATION_REPLACE ] +punctuation["#"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["$"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["%"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["&"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["*"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["+"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["/"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["="] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["@"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation["^"] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[cent] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[pound] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[yen] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[euro] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[not_sign] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[copyright_sign] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[registered] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[trademark] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[degree] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[plus_minus] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[multiply] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[divide] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[infinity] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[almost_equal] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[not_equal] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[lt_or_equal] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[gt_or_equal] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[square_root] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[cube_root] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[dagger] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[double_dagger] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[section] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[prime] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[double_prime] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] +punctuation[per_mille] = [ LEVEL_SOME, PUNCTUATION_REPLACE ] + +punctuation[left_arrow] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[right_arrow] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[middle_dot] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[bullet] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[triangular_bullet] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[hyphen_bullet] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[black_square] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[white_square] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[white_bullet] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[white_circle] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[black_diamond] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[black_circle] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[check_mark] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[heavy_check_mark] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[x_shaped_bullet] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[heavy_right_arrow] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[right_arrowhead] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[SO_black_square] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[SO_black_diamond] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[one_quarter] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[one_half] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[three_quarters] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] + +punctuation[superscript_zero] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript1] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript2] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript3] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript4] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript5] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript6] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript7] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript8] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript9] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript_plus] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript_minus] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript_equals] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript_left_paren] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscript_right_paren] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[superscriptn] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript_zero] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript1] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript2] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript3] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript4] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript5] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript6] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript7] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript8] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript9] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript_plus] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript_minus] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript_equals] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript_left_paren] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] +punctuation[subscript_right_paren] = [ LEVEL_NONE, PUNCTUATION_REPLACE ] + +def getPunctuationInfo(character): + """Given a punctuation character, return the value + [punctuation_style, punctuation_action] or None + + Arguments: + - character: the punctuation character to get the information for + + Returns return the value [punctuation_style, punctuation_action] + or None + """ + + return punctuation.get(character) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/resource_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/resource_manager.py new file mode 100644 index 0000000..d06705f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/resource_manager.py @@ -0,0 +1,374 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import traceback + +class TryFunction(): + def __init__(self, function): + self.function = function + def runSignal(self, app): + try: + return self.function(app) + except Exception as e: + print('try signal',e , traceback.print_exc()) + def runInputEvent(self, script=None, inputEvent=None): + try: + return self.function(script, inputEvent) + except Exception as e: + print('try input event',e , traceback.print_exc()) + def getFunction(self): + return self.function + def setFunction(self, function): + self.function = function + +class ResourceEntry(): + def __init__(self, entryType, resource1 = None, function = None, tryFunction= None, resourceText = '', resource2 = None, resource3 = None, resource4 = None): + # function based init + self.entryType = entryType # 'keyboard' = Keyboard, 'subscription' = Subscription, 'signal' = Signal, 'api'= Dynamic API, 'settings' = gSetttings + self.resource1 = resource1 + self.resource2 = resource2 + self.resource3 = resource3 + self.resource4 = resource4 + self.function = function + self.tryFunction = tryFunction + self.resourceText = resourceText + + def getEntryType(self): + return self.entryType + def getResourceText(self): + return self.resourceText + def getResource1(self): + return self.resource1 + def getResource2(self): + return self.resource2 + def getResource3(self): + return self.resource3 + def getResource4(self): + return self.resource4 + def getFunction(self): + return self.function + def getTryFunction(self): + return self.tryFunction + +class ResourceContext(): + def __init__(self, app, name): + self.app = app + self.name = name + self.gestures = {} # gestures added by the context + self.subscriptions = {} # subscription to signals by the context + self.apis = {} + self.signals = {} + self.settings = {} + + def getName(self): + return self.name + def getGestures(self): + return self.gestures + def getSubscriptions(self): + return self.subscriptions + def getSignals(self): + return self.signals + def getAPIs(self): + return self.apis + def getSettings(self): + return self.settings + def hasSettings(self, profile, application, sub_setting_name): + try: + d = self.getSettings()[profile][application][sub_setting_name] + return True + except KeyError: + return False + def addSetting(self, profile, application, sub_setting_name, entry): + # add profile + try: + d = self.settings[profile] + except KeyError: + self.settings[profile]= {} + # add application + try: + d = self.settings[profile][application] + except KeyError: + self.settings[profile][application] = {} + # add entry + self.settings[profile][application][sub_setting_name] = entry + + print('add', 'settings', self.getName(), profile, application, entry.getResourceText()) + + + def hasAPI(self, application, api): + try: + d = self.getAPIs()[application][api] + return True + except KeyError: + return False + def addAPI(self, application, api, entry): + # add application + try: + d = self.apis[application] + except KeyError: + self.apis[application] = {} + # add entry + self.apis[application][api] = entry + print('add', 'api', self.getName(), application, api) + + def removeAPI(self, application, api): + try: + del self.apis[application][api] + except KeyError as e: + print(e) + try: + if len(self.getAPIs()[application]) == 0: + del self.apis[application] + except KeyError: + pass + print('remove', 'apis', self.getName(), application, api) + + def addGesture(self, profile, application, gesture, entry): + # add profile + try: + d = self.gestures[profile] + except KeyError: + self.gestures[profile]= {} + # add application + try: + d = self.gestures[profile][application] + except KeyError: + self.gestures[profile][application] = {} + # add entry + self.gestures[profile][application][gesture] = entry + print('add', 'gesture', self.getName(), profile, application, entry.getResourceText()) + def removeGesture(self, gesture): + gestureCopy = self.getGestures().copy() + for profile, applicationDict in gestureCopy.items(): + for application, keyDict in applicationDict.copy().items(): + try: + del self.getGestures()[profile][application][gesture] + if len(self.getGestures()[profile][application]) == 0: + del self.getGestures()[profile][application] + if len(self.getGestures()[profile]) == 0: + del self.getGestures()[profile] + except KeyError: + pass + + print('remove', 'gesture', self.getName(), profile, application, gesture) + + def addSubscription(self, signalName, function, entry): + # add entry + try: + e = self.subscriptions[signalName] + except KeyError: + self.subscriptions[signalName] = {} + self.subscriptions[signalName][function] = entry + print('add', 'subscription', self.getName(), entry.getResourceText(), entry.function) + + def removeSubscriptionByFunction(self, function): + for signalName, functionDict in self.getSubscriptions().copy().items(): + for functionKey, entry in functionDict.copy().items(): + try: + if function == entry.function: + del self.getSubscriptions()[signalName][entry.function] + elif function == entry.tryFunction: + del self.getSubscriptions()[signalName][entry.function] + except KeyError as e: + print(e) + try: + if len(self.getSubscriptions()[signalName]) == 0: + del self.getSubscriptions()[signalName] + except KeyError: + pass + print('remove', 'subscription', self.getName(), function) + def addSignal(self, signal, entry): + # add entry + self.signals[signal] = entry + print('add', 'signal', self.getName(), entry.getResourceText()) + def removeSignal(self, signal): + print('remove', 'signal', self.getName(), entry.getResourceText()) + + def unregisterAllResources(self): + try: + self.unregisterAllGestures() + self.unregisterAllSubscriptions() + self.unregisterAllSignals() + self.unregisterAllAPI() + except Exception as e: + print(e) + + def unregisterAllAPI(self): + dynamicApiManager = self.app.getDynamicApiManager() + for application, value in self.getAPIs().copy().items(): + for key, entry in value.copy().items(): + try: + dynamicApiManager.unregisterAPI(key, application, self.getName()) + except Exception as e: + print(e) + print('unregister api ', self.getName(), entry.getEntryType(), entry.getResourceText()) + def unregisterAllGestures(self): + APIHelper = self.app.getAPIHelper() + + for profile, profileValue in self.getGestures().copy().items(): + for application, applicationValue in profileValue.copy().items(): + for gesture, entry in applicationValue.copy().items(): + if entry.getEntryType() == 'keyboard': + try: + APIHelper.unregisterShortcut(entry.getResource1(), self.getName()) + except Exception as e: + print(e) + print('unregister gesture', self.getName(), entry.getEntryType(), profile, application, entry.getResourceText()) + def unregisterAllSignals(self): + pass + # how to remove signals???? + + def unregisterAllSubscriptions(self): + SignalManager = self.app.getSignalManager() + + for signalName, entryDict in self.getSubscriptions().copy().items(): + for function, entry in entryDict.copy().items(): + try: + SignalManager.disconnectSignalByFunction(entry.tryFunction, self.getName()) + except Exception as e: + print(e) + print('unregister subscription', self.getName(), entry.getEntryType(), entry.getResourceText()) + +class ResourceManager(): + def __init__(self, app): + self.app = app + self.resourceContextDict = {} + def getResourceContextDict(self): + return self.resourceContextDict + + def addResourceContext(self, contextName, overwrite = False): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if resourceContext: + if not overwrite: + return + resourceContext = ResourceContext(self.app, contextName) + self.resourceContextDict[contextName] = resourceContext + print('add {}'.format(contextName)) + + def removeResourceContext(self, contextName): + if not contextName: + return + + try: + self.resourceContextDict[contextName].unregisterAllResources() + except: + pass + + # temp + try: + print('_________', 'summery', self.resourceContextDict[contextName].getName(), '_________') + print('api', self.resourceContextDict[contextName].getAPIs()) + print('signals', self.resourceContextDict[contextName].getSignals()) + print('subscriptions', self.resourceContextDict[contextName].getSubscriptions()) + print('gestrues ', self.resourceContextDict[contextName].getGestures()) + print('_________', self.resourceContextDict[contextName].getName(), '_________') + except: + pass + # temp + try: + del self.resourceContextDict[contextName] + except KeyError: + pass + print('rm {}'.format(contextName)) + + def getResourceContext(self, contextName): + if not contextName: + return None + try: + return self.resourceContextDict[contextName] + except KeyError: + return None + + def addAPI(self, application, api, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + entry = None + resourceContext.addAPI(application, api, entry) + def removeAPI(self, application, api, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + resourceContext.removeAPI(application, api) + def addGesture(self, profile, application, gesture, entry, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + entry = None + resourceContext.addGesture(profile, application, gesture, entry) + def removeGesture(self, gesture, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + resourceContext.removeGesture(gesture) + def addSubscription(self, subscription, entry, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + entry = None + resourceContext.addSubscription(subscription, entry) + def removeSubscriptionByFunction(self, function, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + resourceContext.removeSubscriptionByFunction(function) + def addSignal(self, signal, entry, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + entry = None + resourceContext.addSignal(signal, entry) + def removeSignal(self, signal, contextName = None): + if not contextName: + return + resourceContext = self.getResourceContext(contextName) + if not resourceContext: + return + resourceContext.removeSignal(signal) + def printContext(self): + for k, v in self.resourceContextDict.items(): + print('plugin', k) + for k1, v1 in v.getGestures().items(): + print(' profile', k1) + for k2, v2 in v1.items(): + print(' application', k2) + for k3, v3 in v2.items(): + print(' value', k3, v3) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script.py new file mode 100644 index 0000000..459e30f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script.py @@ -0,0 +1,642 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Each script maintains a set of key bindings, braille bindings, and +AT-SPI event listeners. The key bindings are an instance of +KeyBindings. The braille bindings are also a dictionary where the +keys are BrlTTY command integers and the values are instances of +InputEventHandler. The listeners field is a dictionary where the keys +are AT-SPI event names and the values are function pointers. + +Instances of scripts are intended to be created solely by the +script manager. + +This Script class is not intended to be instantiated directly. +Instead, it is expected that subclasses of the Script class will be +created in their own module. The module defining the Script subclass +is also required to have a 'getScript(app)' method that returns an +instance of the Script subclass. See default.py for an example.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import ax_event_synthesizer +from . import action_presenter +from . import braille_generator +from . import date_and_time_presenter +from . import debug +from . import event_manager +from . import flat_review_presenter +from . import formatting +from . import keybindings +from . import label_inference +from . import learn_mode_presenter +from . import mouse_review +from . import notification_presenter +from . import object_navigator +from . import cthulhu_state +from . import script_manager +from . import script_utilities +from . import settings +from . import settings_manager +from . import sound_generator +from . import speech_and_verbosity_manager +from . import speech_generator +from . import structural_navigation +from . import bookmarks +from . import tutorialgenerator +from . import where_am_i_presenter +from .ax_object import AXObject + +_eventManager = event_manager.getManager() +_scriptManager = script_manager.getManager() +_settingsManager = settings_manager.getManager() + +class Script: + """The specific focus tracking scripts for applications. + """ + + def __init__(self, app): + """Creates a script for the given application, if necessary. + This method should not be called by anyone except the + script manager. + + Arguments: + - app: the Python Accessible application to create a script for + """ + self.app = app + + if app: + self.name = AXObject.get_name(self.app) or "default" + else: + self.name = "default" + + self.name += " (module=" + self.__module__ + ")" + + self.listeners = self.getListeners() + + # By default, handle events for non-active applications. + # + self.presentIfInactive = True + + self.utilities = self.getUtilities() + self.labelInference = self.getLabelInference() + self.structuralNavigation = self.getStructuralNavigation() + self.caretNavigation = self.getCaretNavigation() + self.bookmarks = self.getBookmarks() + self.liveRegionManager = self.getLiveRegionManager() + self.notificationPresenter = self.getNotificationPresenter() + self.flatReviewPresenter = self.getFlatReviewPresenter() + self.speechAndVerbosityManager = self.getSpeechAndVerbosityManager() + self.dateAndTimePresenter = self.getDateAndTimePresenter() + self.objectNavigator = self.getObjectNavigator() + self.whereAmIPresenter = self.getWhereAmIPresenter() + self.learnModePresenter = self.getLearnModePresenter() + self.mouseReviewer = self.getMouseReviewer() + self.eventSynthesizer = self.getEventSynthesizer() + self.actionPresenter = self.getActionPresenter() + + self.chat = self.getChat() + self.inputEventHandlers = {} + self.pointOfReference = {} + self.setupInputEventHandlers() + self.keyBindings = self.getKeyBindings() + self.brailleBindings = self.getBrailleBindings() + + self.formatting = self.getFormatting() + self.brailleGenerator = self.getBrailleGenerator() + self.soundGenerator = self.getSoundGenerator() + self.speechGenerator = self.getSpeechGenerator() + self.generatorCache = {} + self.eventCache = {} + self.spellcheck = self.getSpellCheck() + self.tutorialGenerator = self.getTutorialGenerator() + + self.findCommandRun = False + self._lastCommandWasStructNav = False + + msg = f'SCRIPT: {self.name} initialized' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def __str__(self): + return f"{self.name}" + + def getListeners(self): + """Sets up the AT-SPI event listeners for this script. + + Returns a dictionary where the keys are AT-SPI event names + and the values are script methods. + """ + return {} + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings.""" + pass + + def getKeyBindings(self): + """Defines the key bindings for this script. + + Returns an instance of keybindings.KeyBindings. + """ + return keybindings.KeyBindings() + + def getToolkitKeyBindings(self): + """Returns the toolkit-specific keybindings for this script.""" + + return keybindings.KeyBindings() + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + return keybindings.KeyBindings() + + def getPluginKeyBindings(self): + """Returns the plugin keybindings for this script.""" + + from . import debug + debug.printMessage(debug.LEVEL_INFO, "SCRIPT: getPluginKeyBindings() called", True) + + plugin_bindings = keybindings.KeyBindings() + + # Get the plugin system manager + try: + from . import plugin_system_manager + manager = plugin_system_manager.getManager() + debug.printMessage(debug.LEVEL_INFO, f"SCRIPT: Plugin manager: {manager}", True) + if manager: + # Get all active plugins + active_plugins = manager.get_active_plugins() + debug.printMessage(debug.LEVEL_INFO, f"SCRIPT: Found {len(active_plugins)} active plugins", True) + for plugin in active_plugins: + # Get bindings from each plugin + bindings = plugin.get_bindings() + debug.printMessage(debug.LEVEL_INFO, f"SCRIPT: Plugin {plugin.name} has bindings: {bindings}", True) + if bindings: + # Add each binding from the plugin to our collection + for binding in bindings.keyBindings: + plugin_bindings.add(binding) + debug.printMessage(debug.LEVEL_INFO, f"SCRIPT: Added plugin binding: {binding.asString()}", True) + except Exception as e: + debug.printMessage(debug.LEVEL_INFO, f"Could not get plugin keybindings: {e}", True) + import traceback + debug.printMessage(debug.LEVEL_INFO, traceback.format_exc(), True) + + debug.printMessage(debug.LEVEL_INFO, f"SCRIPT: Returning {len(plugin_bindings.keyBindings)} plugin bindings", True) + return plugin_bindings + + def getBrailleBindings(self): + """Defines the braille bindings for this script. + + Returns a dictionary where the keys are BrlTTY commands and the + values are InputEventHandler instances. + """ + return {} + + def getFormatting(self): + """Returns the formatting strings for this script.""" + return formatting.Formatting(self) + + def getBrailleGenerator(self): + """Returns the braille generator for this script. + """ + return braille_generator.BrailleGenerator(self) + + def getSoundGenerator(self): + """Returns the sound generator for this script.""" + return sound_generator.SoundGenerator(self) + + def getSpeechGenerator(self): + """Returns the speech generator for this script. + """ + return speech_generator.SpeechGenerator(self) + + def getTutorialGenerator(self): + """Returns the tutorial generator for this script. + """ + return tutorialgenerator.TutorialGenerator(self) + + def getChat(self): + """Returns the 'chat' class for this script. + """ + return None + + def getSpellCheck(self): + """Returns the spellcheck support for this script.""" + return None + + def getCaretNavigation(self): + """Returns the caret navigation support for this script.""" + return None + + def getUtilities(self): + """Returns the utilities for this script.""" + return script_utilities.Utilities(self) + + def getLabelInference(self): + """Returns the label inference functionality for this script.""" + return label_inference.LabelInference(self) + + def getEnabledStructuralNavigationTypes(self): + """Returns a list of the structural navigation object types + enabled in this script. + """ + return [] + + def getStructuralNavigation(self): + """Returns the 'structural navigation' class for this script.""" + types = self.getEnabledStructuralNavigationTypes() + enable = _settingsManager.getSetting('structuralNavigationEnabled') + return structural_navigation.StructuralNavigation(self, types, enable) + + def getLiveRegionManager(self): + """Returns the live region support for this script.""" + return None + + def getNotificationPresenter(self): + return notification_presenter.getPresenter() + + def getFlatReviewPresenter(self): + return flat_review_presenter.getPresenter() + + def getDateAndTimePresenter(self): + return date_and_time_presenter.getPresenter() + + def getObjectNavigator(self): + return object_navigator.getNavigator() + + def getSpeechAndVerbosityManager(self): + return speech_and_verbosity_manager.getManager() + + def getWhereAmIPresenter(self): + return where_am_i_presenter.getPresenter() + + def getLearnModePresenter(self): + return learn_mode_presenter.getPresenter() + + def getActionPresenter(self): + return action_presenter.getPresenter() + + def getMouseReviewer(self): + return mouse_review.getReviewer() + + def getEventSynthesizer(self): + return ax_event_synthesizer.getSynthesizer() + + def useStructuralNavigationModel(self, debugOutput=True): + """Returns True if we should use structural navigation. Most + scripts will have no need to override this. Gecko does however + because within an HTML document there are times when we do want + to use it and times when we don't even though it is enabled, + e.g. in a form field. + """ + return self.structuralNavigation.enabled + + def getBookmarks(self): + """Returns the "bookmarks" class for this script. + """ + try: + return self.bookmarks + except AttributeError: + self.bookmarks = bookmarks.Bookmarks(self) + return self.bookmarks + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application. + """ + return None + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return {} + + def registerEventListeners(self): + """Tells the event manager to start listening for all the event types + of interest to the script. + + Arguments: + - script: the script. + """ + + _eventManager.registerScriptListeners(self) + + def deregisterEventListeners(self): + """Tells the event manager to stop listening for all the event types + of interest to the script. + + Arguments: + - script: the script. + """ + + _eventManager.deregisterScriptListeners(self) + + def processObjectEvent(self, event): + """Processes all AT-SPI object events of interest to this + script. The interest in events is specified via the + 'listeners' field that was defined during the construction of + this script. + + Note that this script may be passed events it doesn't care + about, so it needs to react accordingly. + + Arguments: + - event: the Event + """ + + role = AXObject.get_role(event.source) + if role == Atspi.Role.INVALID: + msg = 'ERROR: Not processing object event for invalid object' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + # Check to see if we really want to process this event. + # + processEvent = (cthulhu_state.activeScript == self \ + or self.presentIfInactive) + if role == Atspi.Role.PROGRESS_BAR \ + and not processEvent \ + and settings.progressBarVerbosity == settings.PROGRESS_BAR_ALL: + processEvent = True + + if not processEvent: + return + + if self.skipObjectEvent(event): + return + + # Clear the generator cache for each event. + # + self.generatorCache = {} + + # This calls the first listener it finds whose key *begins with* or is + # the same as the event.type. The reason we do this is that the event + # type in the listeners dictionary may not be as specific as the event + # type we received (e.g., the listeners dictionary might contain the + # key "object:state-changed:" and the event.type might be + # "object:state-changed:focused". [[[TODO: WDW - the order of the + # keys is *not* deterministic, and is not guaranteed to be related + # to the order in which they were added. So...we need to do something + # different here. Logged as bugzilla bug 319781.]]] + # + for key in self.listeners.keys(): + if event.type.startswith(key): + self.listeners[key](event) + + def _getQueuedEvent(self, eventType, detail1=None, detail2=None, any_data=None): + cachedEvent, eventTime = self.eventCache.get(eventType, [None, 0]) + if not cachedEvent: + tokens = ["SCRIPT: No queued event of type", eventType] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if detail1 is not None and detail1 != cachedEvent.detail1: + tokens = ["SCRIPT: Queued event's detail1 (", cachedEvent.detail1, + ") doesn't match", detail1] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if detail2 is not None and detail2 != cachedEvent.detail2: + tokens = ["SCRIPT: Queued event's detail2 (", cachedEvent.detail2, + ") doesn't match", detail2] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if any_data is not None and any_data != cachedEvent.any_data: + tokens = ["SCRIPT: Queued event's any_data (", + cachedEvent.any_data, ") doesn't match", any_data] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + tokens = ["SCRIPT: Found matching queued event:", cachedEvent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return cachedEvent + + def skipObjectEvent(self, event): + """Gives us, and scripts, the ability to decide an event isn't + worth taking the time to process under the current circumstances. + + Arguments: + - event: the Event + + Returns True if we shouldn't bother processing this object event. + """ + + cachedEvent, eventTime = self.eventCache.get(event.type, [None, 0]) + if not cachedEvent or cachedEvent == event: + return False + + focus = ["object:state-changed:focused"] + typing = ["object:text-changed:insert", "object:text-changed:delete"] + arrowing = ["object:text-caret-moved", "object:text-selection-changed", + "object:selection-changed", "object:active-descendant-changed"] + + skip = False + if (event.type in arrowing or event.type in typing) \ + and event.source == cachedEvent.source: + skip = True + reason = "more recent event of the same type in the same object" + elif event.type in focus and event.source != cachedEvent.source \ + and event.type == cachedEvent.type \ + and event.detail1 == cachedEvent.detail1: + skip = True + reason = "more recent event of the same type in a different object" + elif event.type.endswith("system") and event.source == cachedEvent.source: + skip = True + reason = "more recent system event in the same object" + elif event.type.startswith("object:state-changed") \ + and event.type == cachedEvent.type \ + and event.source == cachedEvent.source \ + and event.detail1 == cachedEvent.detail1: + skip = True + reason = "appears to be duplicate state-changed event" + + if skip: + tokens = ["SCRIPT: Skipping object event:", reason, cachedEvent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return skip + + def consumesKeyboardEvent(self, keyboardEvent): + """Called when a key is pressed on the keyboard. + + Arguments: + - keyboardEvent: an instance of input_event.KeyboardEvent + + Returns True if the event is of interest. + """ + + user_bindings = None + user_bindings_map = settings.keyBindingsMap + if self.__module__ in user_bindings_map: + user_bindings = user_bindings_map[self.__module__] + elif "default" in user_bindings_map: + user_bindings = user_bindings_map["default"] + + consumes = False + self._lastCommandWasStructNav = False + if user_bindings: + handler = user_bindings.getInputHandler(keyboardEvent) + if handler \ + and handler.function in self.structuralNavigation.functions: + consumes = self.useStructuralNavigationModel() + if consumes: + self._lastCommandWasStructNav = True + else: + consumes = handler is not None + if not consumes: + handler = self.keyBindings.getInputHandler(keyboardEvent) + if handler \ + and handler.function in self.structuralNavigation.functions: + consumes = self.useStructuralNavigationModel() + if consumes: + self._lastCommandWasStructNav = True + else: + consumes = handler is not None + return consumes + + def consumesBrailleEvent(self, brailleEvent): + """Called when a key is pressed on the braille display. + + Arguments: + - brailleEvent: an instance of input_event.KeyboardEvent + + Returns True if the event is of interest. + """ + user_bindings = None + user_bindings_map = settings.brailleBindingsMap + if self.__module__ in user_bindings_map: + user_bindings = user_bindings_map[self.__module__] + elif "default" in user_bindings_map: + user_bindings = user_bindings_map["default"] + + command = brailleEvent.event["command"] + consumes = False + if user_bindings: + consumes = command in user_bindings + if not consumes: + consumes = command in self.brailleBindings + return consumes + + def processBrailleEvent(self, brailleEvent): + """Called whenever a key is pressed on the Braille display. + + This method will primarily use the brailleBindings field of + this script instance see if this script has an interest in the + event. + + NOTE: there is latent, but unsupported, logic for allowing + the user's user-settings.py file to extend and/or override + the brailleBindings for a script. + + Arguments: + - brailleEvent: an instance of input_event.BrailleEvent + """ + + # We'll annotate the event with a reference to this script. + # This will allow external scripts to muck with the script + # instance if they wish. + # + brailleEvent.script = self + + # We'll let the user bindings take precedence. First, we'll + # check to see if they have bindings specific for the particular + # application, then we'll check to see if they have any default + # bindings to use. + # + # [[[TODO: WDW - for performance, these bindings should probably + # be conflated at initialization time.]]] + # + consumed = False + user_bindings = None + command = brailleEvent.event["command"] + + user_bindings_map = settings.brailleBindingsMap + if self.name in user_bindings_map: + user_bindings = user_bindings_map[self.name] + elif "default" in user_bindings_map: + user_bindings = user_bindings_map["default"] + + if user_bindings and command in user_bindings: + handler = user_bindings[command] + consumed = handler.processInputEvent(self, brailleEvent) + + if (not consumed) and command in self.brailleBindings: + handler = self.brailleBindings[command] + consumed = handler.processInputEvent(self, brailleEvent) + + return consumed + + def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): + """Called when the visual object with focus changes. + + The primary purpose of this method is to present locus of focus + information to the user. + + NOTE: scripts should not call this method directly. Instead, + a script should call cthulhu.setLocusOfFocus, which will eventually + result in this method being called. + + Arguments: + - event: if not None, the Event that caused the change + - oldLocusOfFocus: Accessible that is the old locus of focus + - newLocusOfFocus: Accessible that is the new locus of focus + """ + pass + + def isActivatableEvent(self, event): + """Returns True if the given event is one that should cause this + script to become the active script. This is only a hint to + the focus tracking manager and it is not guaranteed this + request will be honored. Note that by the time the focus + tracking manager calls this method, it thinks the script + should become active. This is an opportunity for the script + to say it shouldn't. + """ + return True + + def forceScriptActivation(self, event): + """Allows scripts to insist that they should become active.""" + + return False + + def activate(self): + """Called when this script is activated.""" + pass + + def deactivate(self): + """Called when this script is deactivated.""" + pass + + def getTransferableAttributes(self): + return {} diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_manager.py new file mode 100644 index 0000000..a8508d2 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_manager.py @@ -0,0 +1,408 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2011. Cthulhu Team." +__license__ = "LGPL" + +import importlib + +from . import debug +from . import cthulhu_state +from .ax_object import AXObject +from .ax_utilities import AXUtilities +from .scripts import apps, toolkits + +class ScriptManager: + + def __init__(self): + debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Initializing", True) + self.appScripts = {} + self.toolkitScripts = {} + self.customScripts = {} + self._appModules = apps.__all__ + self._toolkitModules = toolkits.__all__ + self._defaultScript = None + self._scriptPackages = \ + ["cthulhu-scripts", + "cthulhu.scripts", + "cthulhu.scripts.apps", + "cthulhu.scripts.toolkits"] + self._appNames = \ + {'Icedove': 'Thunderbird', + 'Nereid': 'Banshee', + 'gnome-calculator': 'gcalctool', + 'gtk-window-decorator': 'switcher', + 'marco': 'switcher', + 'xfce4-notifyd': 'notification-daemon', + 'mate-notification-daemon': 'notification-daemon', + 'metacity': 'switcher', + 'pluma': 'gedit', + } + self._toolkitNames = \ + {'WebKitGTK': 'WebKitGtk', 'GTK': 'gtk'} + + self.setActiveScript(None, "__init__") + self._active = False + debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Initialized", True) + + def activate(self): + """Called when this script manager is activated.""" + + debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activating", True) + self._defaultScript = self.getScript(None) + self._defaultScript.registerEventListeners() + self.setActiveScript(self._defaultScript, "activate") + self._active = True + debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Activated", True) + + def deactivate(self): + """Called when this script manager is deactivated.""" + + debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Deactivating", True) + if self._defaultScript: + self._defaultScript.deregisterEventListeners() + self._defaultScript = None + self.setActiveScript(None, "deactivate") + self.appScripts = {} + self.toolkitScripts = {} + self.customScripts = {} + self._active = False + debug.printMessage(debug.LEVEL_INFO, "SCRIPT MANAGER: Deactivated", True) + + def getModuleName(self, app): + """Returns the module name of the script to use for application app.""" + + if app is None: + msg = "SCRIPT MANAGER: Cannot get module name for null app" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None + + name = AXObject.get_name(app) + if not name: + msg = "SCRIPT MANAGER: Cannot get module name for nameless app" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None + + altNames = list(self._appNames.keys()) + if name.endswith(".py") or name.endswith(".bin"): + name = name.split('.')[0] + elif name.startswith("org.") or name.startswith("com."): + name = name.split('.')[-1] + + names = [n for n in altNames if n.lower() == name.lower()] + if names: + name = self._appNames.get(names[0]) + else: + for nameList in (self._appModules, self._toolkitModules): + names = [n for n in nameList if n.lower() == name.lower()] + if names: + name = names[0] + break + + tokens = ["SCRIPT MANAGER: Mapped", app, "to", name] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return name + + def _toolkitForObject(self, obj): + """Returns the name of the toolkit associated with obj.""" + + name = AXObject.get_attribute(obj, 'toolkit') + return self._toolkitNames.get(name, name) + + def _scriptForRole(self, obj): + if AXUtilities.is_terminal(obj): + return 'terminal' + + return '' + + def _newNamedScript(self, app, name): + """Attempts to locate and load the named module. If successful, returns + a script based on this module.""" + + if not (app and name): + return None + + script = None + for package in self._scriptPackages: + moduleName = '.'.join((package, name)) + try: + module = importlib.import_module(moduleName) + except ImportError: + continue + except OSError: + debug.examineProcesses() + + tokens = ["SCRIPT MANAGER: Found", moduleName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + try: + if hasattr(module, 'getScript'): + script = module.getScript(app) + else: + script = module.Script(app) + break + except Exception as error: + tokens = ["SCRIPT MANAGER: Could not load", moduleName, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return script + + def _createScript(self, app, obj=None): + """For the given application, create a new script instance.""" + + moduleName = self.getModuleName(app) + script = self._newNamedScript(app, moduleName) + if script: + return script + + objToolkit = self._toolkitForObject(obj) + script = self._newNamedScript(app, objToolkit) + if script: + return script + + toolkitName = AXObject.get_application_toolkit_name(app) + if app and toolkitName: + script = self._newNamedScript(app, toolkitName) + + if not script: + script = self.getDefaultScript(app) + tokens = ["SCRIPT MANAGER: Default script created for", app, "(obj: ", obj, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return script + + def getDefaultScript(self, app=None): + if not app and self._defaultScript: + return self._defaultScript + + from .scripts import default + script = default.Script(app) + + if not app: + self._defaultScript = script + + return script + + def sanityCheckScript(self, script): + if not self._active: + return script + + if AXUtilities.is_application_in_desktop(script.app): + return script + + newScript = self._getScriptForAppReplicant(script.app) + if newScript: + return newScript + + tokens = ["WARNING: Failed to get a replacement script for", script.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return script + + def getScriptForMouseButtonEvent(self, event): + isActive = AXUtilities.is_active(cthulhu_state.activeWindow) + tokens = ["SCRIPT MANAGER:", cthulhu_state.activeWindow, "is active:", isActive] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if isActive and cthulhu_state.activeScript: + return cthulhu_state.activeScript + + script = self.getDefaultScript() + activeWindow = script.utilities.activeWindow() + if not activeWindow: + return script + + focusedObject = AXUtilities.get_focused_object(activeWindow) + if focusedObject: + return self.getScript(AXObject.get_application(focusedObject), focusedObject) + + return self.getScript(AXObject.get_application(activeWindow), activeWindow) + + def getScript(self, app, obj=None, sanityCheck=False): + """Get a script for an app (and make it if necessary). This is used + instead of a simple calls to Script's constructor. + + Arguments: + - app: the Python app + + Returns an instance of a Script. + """ + + customScript = None + appScript = None + toolkitScript = None + + roleName = self._scriptForRole(obj) + if roleName: + customScripts = self.customScripts.get(app, {}) + customScript = customScripts.get(roleName) + if not customScript: + customScript = self._newNamedScript(app, roleName) + customScripts[roleName] = customScript + self.customScripts[app] = customScripts + + objToolkit = self._toolkitForObject(obj) + if objToolkit: + toolkitScripts = self.toolkitScripts.get(app, {}) + toolkitScript = toolkitScripts.get(objToolkit) + if not toolkitScript: + toolkitScript = self._createScript(app, obj) + toolkitScripts[objToolkit] = toolkitScript + self.toolkitScripts[app] = toolkitScripts + + try: + if not app: + appScript = self.getDefaultScript() + elif app in self.appScripts: + appScript = self.appScripts[app] + else: + appScript = self._createScript(app, None) + self.appScripts[app] = appScript + except Exception as error: + tokens = ["SCRIPT MANAGER: Exception getting app script for", app, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + appScript = self.getDefaultScript() + + if customScript: + return customScript + + # Only defer to the toolkit script for this object if the app script + # is based on a different toolkit. + if toolkitScript and not (AXUtilities.is_frame(obj) or AXUtilities.is_status_bar(obj)) \ + and not issubclass(appScript.__class__, toolkitScript.__class__): + return toolkitScript + + if app and sanityCheck: + appScript = self.sanityCheckScript(appScript) + + return appScript + + def setActiveScript(self, newScript, reason=None): + """Set the new active script. + + Arguments: + - newScript: the new script to be made active. + """ + + if cthulhu_state.activeScript == newScript: + return + + if cthulhu_state.activeScript: + cthulhu_state.activeScript.deactivate() + + cthulhu_state.activeScript = newScript + if not newScript: + return + + newScript.activate() + + # Register plugin keybindings with the new active script + from . import cthulhu + plugin_manager = cthulhu.cthulhuApp.getPluginSystemManager() + if plugin_manager: + pass # plugin_manager.register_plugin_keybindings_with_active_script() + + tokens = ["SCRIPT MANAGER: Setting active script to", newScript, "reason:", reason] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def _getScriptForAppReplicant(self, app): + if not self._active: + return None + + pid = AXObject.get_process_id(app) + if pid == -1: + return None + + items = self.appScripts.items() + for a, script in items: + if AXObject.get_process_id(a) != pid: + continue + if a != app and AXUtilities.is_application_in_desktop(a): + if script.app is None: + script.app = a + tokens = ["SCRIPT MANAGER: Script for app replicant:", script, script.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return script + + return None + + def reclaimScripts(self): + """Compares the list of known scripts to the list of known apps, + deleting any scripts as necessary. + """ + + msg = "SCRIPT MANAGER: Checking and cleaning up scripts." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + appList = list(self.appScripts.keys()) + for app in appList: + if AXUtilities.is_application_in_desktop(app): + continue + + try: + appScript = self.appScripts.pop(app) + except KeyError: + tokens = ["SCRIPT MANAGER:", app, "not found in appScripts"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + continue + + tokens = ["SCRIPT MANAGER: Old script for app found:", appScript, appScript.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + newScript = self._getScriptForAppReplicant(app) + if newScript: + tokens = ["SCRIPT MANAGER: Transferring attributes:", newScript, newScript.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + attrs = appScript.getTransferableAttributes() + for attr, value in attrs.items(): + tokens = ["SCRIPT MANAGER: Setting", attr, "to", value] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + setattr(newScript, attr, value) + + del appScript + + try: + toolkitScripts = self.toolkitScripts.pop(app) + except KeyError: + pass + else: + for toolkitScript in toolkitScripts.values(): + del toolkitScript + + try: + customScripts = self.customScripts.pop(app) + except KeyError: + pass + else: + for customScript in customScripts.values(): + del customScript + + del app + +_manager = ScriptManager() + +def getManager(): + return _manager diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_utilities.py new file mode 100644 index 0000000..fce7fe6 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/script_utilities.py @@ -0,0 +1,5631 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Commonly-required utility methods needed by -- and potentially + customized by -- application and toolkit scripts. They have + been pulled out from the scripts because certain scripts had + gotten way too large as a result of including these methods.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import functools +import gi +import locale +import math +import re +import subprocess +import time +from difflib import SequenceMatcher + +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +from gi.repository import Gdk +from gi.repository import Gtk + +from . import chnames +from . import colornames +from . import debug +from . import keynames +from . import keybindings +from . import input_event +from . import mathsymbols +from . import messages +from . import cthulhu +from . import cthulhu_state +from . import object_properties +from . import pronunciation_dict +from . import settings +from . import settings_manager +from . import text_attribute_names +from .ax_object import AXObject +from .ax_selection import AXSelection +from .ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +############################################################################# +# # +# Utilities # +# # +############################################################################# + +class Utilities: + + _last_clipboard_update = time.time() + + EMBEDDED_OBJECT_CHARACTER = '\ufffc' + ZERO_WIDTH_NO_BREAK_SPACE = '\ufeff' + SUPERSCRIPT_DIGITS = \ + ['\u2070', '\u00b9', '\u00b2', '\u00b3', '\u2074', + '\u2075', '\u2076', '\u2077', '\u2078', '\u2079'] + SUBSCRIPT_DIGITS = \ + ['\u2080', '\u2081', '\u2082', '\u2083', '\u2084', + '\u2085', '\u2086', '\u2087', '\u2088', '\u2089'] + + flags = re.UNICODE + WORDS_RE = re.compile(r"(\W+)", flags) + SUPERSCRIPTS_RE = re.compile(f"[{''.join(SUPERSCRIPT_DIGITS)}]+", flags) + SUBSCRIPTS_RE = re.compile(f"[{''.join(SUBSCRIPT_DIGITS)}]+", flags) + PUNCTUATION = re.compile(r"[^\w\s]", flags) + + # generatorCache + # + DISPLAYED_DESCRIPTION = 'displayedDescription' + DISPLAYED_LABEL = 'displayedLabel' + DISPLAYED_TEXT = 'displayedText' + KEY_BINDING = 'keyBinding' + NESTING_LEVEL = 'nestingLevel' + NODE_LEVEL = 'nodeLevel' + + def __init__(self, script): + """Creates an instance of the Utilities class. + + Arguments: + - script: the script with which this instance is associated. + """ + + self._script = script + self._clipboardHandlerId = None + self._selectedMenuBarMenu = {} + + ######################################################################### + # # + # Utilities for finding, identifying, and comparing accessibles # + # # + ######################################################################### + + def _isActiveAndShowingAndNotIconified(self, obj): + if not AXUtilities.is_active(obj): + tokens = ["SCRIPT UTILITIES:", obj, "lacks state active"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if AXUtilities.is_iconified(obj): + tokens = ["SCRIPT UTILITIES:", obj, "has state iconified"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if not AXUtilities.is_showing(obj): + tokens = ["SCRIPT UTILITIES:", obj, "lacks state showing"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + @staticmethod + def _getAppCommandLine(app): + if not app: + return "" + + try: + pid = app.get_process_id() + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting process id of", app, ". May be defunct."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + + try: + cmdline = subprocess.getoutput(f"cat /proc/{pid}/cmdline") + except Exception: + return "" + + return cmdline.replace("\x00", " ") + + def canBeActiveWindow(self, window, clearCache=False): + if not window: + return False + + app = AXObject.get_application(window) + tokens = ["SCRIPT UTILITIES: Looking at", window, "from", app, self._getAppCommandLine(app)] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if clearCache: + AXObject.clear_cache(window) + + if not self._isActiveAndShowingAndNotIconified(window): + tokens = ["SCRIPT UTILITIES:", window, "is not active and showing, or is iconified"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["SCRIPT UTILITIES:", window, "can be active window"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def activeWindow(self, *apps): + """Tries to locate the active window; may or may not succeed.""" + + candidates = [] + apps = apps or AXUtilities.get_all_applications(must_have_window=True) + for app in apps: + candidates.extend([c for c in AXObject.iter_children(app, self.canBeActiveWindow)]) + + if not candidates: + tokens = ["SCRIPT UTILITIES: Unable to find active window from", apps] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if len(candidates) == 1: + tokens = ["SCRIPT UTILITIES: Active window is", candidates[0]] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return candidates[0] + + tokens = ["SCRIPT UTILITIES: These windows all claim to be active:", candidates] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + filtered = [] + for candidate in candidates: + if self.isDesktop(candidate): + tokens = ["SCRIPT UTILITIES: Rejecting", candidate, ": it's the desktop frame"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + elif AXObject.get_name(AXObject.get_application(candidate)) == "mutter-x11-frames": + tokens = ["SCRIPT UTILITIES: Rejecting", candidate, ": app is mutter-x11-frames"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + filtered.append(candidate) + + if len(filtered) == 1: + tokens = ["SCRIPT UTILITIES: Active window is believed to be", filtered[0]] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return filtered[0] + + # Some electron apps running in the background claim to be active even when they + # are not. Slack is one such example. We can add others as we go. + suspect_app_names = ["slack", + "discord", + "outline-client", + "whatsapp-desktop-linux"] + refiltered = [] + for frame in filtered: + if AXObject.get_name(AXObject.get_application(frame)) in suspect_app_names: + tokens = ["SCRIPT UTILITIES: Suspecting", frame, "is a non-active Electron app"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + refiltered.append(frame) + + if len(refiltered) == 1: + tokens = ["SCRIPT UTILITIES: Active window is believed to be", refiltered[0]] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return refiltered[0] + + guess = None + if refiltered: + tokens = ["SCRIPT UTILITIES: Still have multiple active windows:", refiltered] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + guess = refiltered[0] + + tokens = ["SCRIPT UTILITIES: Active window is:", guess] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return guess + + def objectAttributes(self, obj, useCache=True): + return AXObject.get_attributes_dict(obj) + + def cellIndex(self, obj): + """Returns the index of the cell which should be used with the + table interface. This is necessary because in some apps we + cannot count on the index in parent being the index we need. + + Arguments: + -obj: the table cell whose index we need. + """ + + attrs = self.objectAttributes(obj) + index = attrs.get('table-cell-index') + if index: + return int(index) + + obj = AXObject.find_ancestor(obj, AXUtilities.is_table_cell_or_header) or obj + return AXObject.get_index_in_parent(obj) + + def childNodes(self, obj): + """Gets all of the children that have RELATION_NODE_CHILD_OF pointing + to this expanded table cell. + + Arguments: + -obj: the Accessible Object + + Returns: a list of all the child nodes + """ + + parent = AXObject.get_parent(obj) + try: + table = parent.queryTable() + except Exception: + return [] + else: + if not AXUtilities.is_expanded(obj): + return [] + + # First see if this accessible implements RELATION_NODE_PARENT_OF. + # If it does, the full target list are the nodes. If it doesn't + # we'll do an old-school, row-by-row search for child nodes. + def pred(x): + return AXObject.get_index_in_parent(x) >= 0 + + nodes = AXObject.get_relation_targets(obj, Atspi.RelationType.NODE_PARENT_OF, pred) + tokens = ["SCRIPT UTILITIES:", len(nodes), "child nodes for", obj, "via node-parent-of"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if nodes: + return nodes + + # Candidates will be in the rows beneath the current row. + # Only check in the current column and stop checking as + # soon as the node level of a candidate is equal or less + # than our current level. + # + row, col = self.coordinatesForCell(obj) + nodeLevel = self.nodeLevel(obj) + for i in range(row+1, table.nRows): + cell = table.getAccessibleAt(i, col) + relation = AXObject.get_relation(cell, Atspi.RelationType.NODE_CHILD_OF) + if not relation: + continue + + nodeOf = relation.get_target(0) + if self.isSameObject(obj, nodeOf): + nodes.append(cell) + elif self.nodeLevel(nodeOf) <= nodeLevel: + break + + tokens = ["SCRIPT UTILITIES:", len(nodes), "child nodes for", obj, "via node-child-of"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return nodes + + def commonAncestor(self, a, b): + """Finds the common ancestor between Accessible a and Accessible b. + + Arguments: + - a: Accessible + - b: Accessible + """ + + tokens = ["SCRIPT UTILITIES: Looking for common ancestor of", a, "and", b] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # Don't do any Zombie checks here, as tempting and logical as it + # may seem as it can lead to chattiness. + if not (a and b): + return None + + if a == b: + return a + + aParents = [a] + parent = AXObject.get_parent_checked(a) + while parent: + aParents.append(parent) + parent = AXObject.get_parent_checked(parent) + aParents.reverse() + + bParents = [b] + parent = AXObject.get_parent_checked(b) + while parent: + bParents.append(parent) + parent = AXObject.get_parent_checked(parent) + bParents.reverse() + + commonAncestor = None + maxSearch = min(len(aParents), len(bParents)) + i = 0 + while i < maxSearch: + if self.isSameObject(aParents[i], bParents[i]): + commonAncestor = aParents[i] + i += 1 + else: + break + + tokens = ["SCRIPT UTILITIES: Common ancestor of", a, "and", b, "is", commonAncestor] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return commonAncestor + + def displayedLabel(self, obj): + """If there is an object labelling the given object, return the + text being displayed for the object labelling this object. + Otherwise, return None. + + Argument: + - obj: the object in question + + Returns the string of the object labelling this object, or None + if there is nothing of interest here. + """ + + try: + return self._script.generatorCache[self.DISPLAYED_LABEL][obj] + except Exception: + if self.DISPLAYED_LABEL not in self._script.generatorCache: + self._script.generatorCache[self.DISPLAYED_LABEL] = {} + labelString = None + + labels = self.labelsForObject(obj) + for label in labels: + labelString = \ + self.appendString(labelString, self.displayedText(label)) + + self._script.generatorCache[self.DISPLAYED_LABEL][obj] = labelString + return self._script.generatorCache[self.DISPLAYED_LABEL][obj] + + def preferDescriptionOverName(self, obj): + return False + + def descriptionsForObject(self, obj): + """Return a list of objects describing obj.""" + + descriptions = AXObject.get_relation_targets(obj, Atspi.RelationType.DESCRIBED_BY) + if not descriptions: + return [] + + labels = AXObject.get_relation_targets(obj, Atspi.RelationType.LABELLED_BY) + if descriptions == labels: + tokens = ["SCRIPT UTILITIES:", obj, + "'s described-by targets are the same as labelled-by targets"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + return descriptions + + def detailsContentForObject(self, obj): + details = self.detailsForObject(obj) + return list(map(self.displayedText, details)) + + def detailsForObject(self, obj, textOnly=True): + """Return a list of objects containing details for obj.""" + + details = AXObject.get_relation_targets(obj, Atspi.RelationType.DETAILS) + if not details and AXUtilities.is_toggle_button(obj) \ + and AXUtilities.is_expanded(obj): + details = [child for child in AXObject.iter_children(obj)] + + if not textOnly: + return details + + textObjects = [] + for detail in details: + textObjects.extend(self.findAllDescendants(detail, self.queryNonEmptyText)) + + return textObjects + + def displayedDescription(self, obj): + """Returns the text being displayed for the object describing obj.""" + + try: + return self._script.generatorCache[self.DISPLAYED_DESCRIPTION][obj] + except Exception: + if self.DISPLAYED_DESCRIPTION not in self._script.generatorCache: + self._script.generatorCache[self.DISPLAYED_DESCRIPTION] = {} + + string = " ".join(map(self.displayedText, self.descriptionsForObject(obj))) + self._script.generatorCache[self.DISPLAYED_DESCRIPTION][obj] = string + return self._script.generatorCache[self.DISPLAYED_DESCRIPTION][obj] + + def displayedText(self, obj): + """Returns the text being displayed for an object. + + Arguments: + - obj: the object + + Returns the text being displayed for an object or None if there isn't + any text being shown. + """ + + # TODO - JD: It's finally time to consider killing this for real. + + try: + return self._script.generatorCache[self.DISPLAYED_TEXT][obj] + except Exception: + displayedText = None + + name = AXObject.get_name(obj) + role = AXObject.get_role(obj) + if role in [Atspi.Role.PUSH_BUTTON, Atspi.Role.LABEL] and name: + return name + + if AXObject.supports_text(obj): + # We should be able to use -1 for the final offset, but that crashes Nautilus. + text = obj.queryText() + displayedText = text.getText(0, text.characterCount) + if self.EMBEDDED_OBJECT_CHARACTER in displayedText: + displayedText = None + + if not displayedText and role not in [Atspi.Role.COMBO_BOX, Atspi.Role.SPIN_BUTTON]: + # TODO - JD: This should probably get nuked. But all sorts of + # existing code might be relying upon this bogus hack. So it + # will need thorough testing when removed. + displayedText = name + + if not displayedText and role in [Atspi.Role.PUSH_BUTTON, Atspi.Role.LIST_ITEM]: + labels = self.unrelatedLabels(obj, minimumWords=1) + if not labels: + labels = self.unrelatedLabels(obj, onlyShowing=False, minimumWords=1) + displayedText = " ".join(map(self.displayedText, labels)) + + if self.DISPLAYED_TEXT not in self._script.generatorCache: + self._script.generatorCache[self.DISPLAYED_TEXT] = {} + + self._script.generatorCache[self.DISPLAYED_TEXT][obj] = displayedText + return self._script.generatorCache[self.DISPLAYED_TEXT][obj] + + def documentFrame(self, obj=None): + """Returns the document frame which is displaying the content. + Note that this is intended primarily for web content.""" + + if not obj: + obj, offset = self.getCaretContext() + + document = AXObject.find_ancestor(obj, AXUtilities.is_document) + if not document and AXUtilities.is_document(cthulhu_state.locusOfFocus): + return cthulhu_state.locusOfFocus + + return document + + def documentFrameURI(self, documentFrame=None): + """Returns the URI of the document frame that is active.""" + + return None + + def frameAndDialog(self, obj): + """Returns the frame and (possibly) the dialog containing obj.""" + + results = [None, None] + + obj = obj or cthulhu_state.locusOfFocus + if not obj: + msg = "SCRIPT UTILITIES: frameAndDialog() called without valid object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return results + + topLevel = self.topLevelObject(obj) + if topLevel is None: + tokens = ["SCRIPT UTILITIES: could not find top-level object for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return results + + dialog_roles = [Atspi.Role.DIALOG, Atspi.Role.FILE_CHOOSER] + if self._treatAlertsAsDialogs(): + dialog_roles.append(Atspi.Role.ALERT) + + role = AXObject.get_role(topLevel) + if role in dialog_roles: + results[1] = topLevel + else: + if role in [Atspi.Role.FRAME, Atspi.Role.WINDOW]: + results[0] = topLevel + + def isDialog(x): + return AXObject.get_role(x) in dialog_roles + + if isDialog(obj): + results[1] = obj + else: + results[1] = AXObject.find_ancestor(obj, isDialog) + + tokens = ["SCRIPT UTILITIES:", obj, "is in frame", results[0], "and dialog", results[1]] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return results + + def presentEventFromNonShowingObject(self, event): + if event.source == cthulhu_state.locusOfFocus: + return True + + return False + + def grabFocusBeforeRouting(self, obj, offset): + """Whether or not we should perform a grabFocus before routing + the cursor via the braille cursor routing keys. + + Arguments: + - obj: the accessible object where the cursor should be routed + - offset: the offset to which it should be routed + + Returns True if we should do an explicit grabFocus on obj prior + to routing the cursor. + """ + + return AXUtilities.is_combo_box(obj) \ + and not self.isSameObject(obj, cthulhu_state.locusOfFocus) + + def hasMatchingHierarchy(self, obj, rolesList): + """Called to determine if the given object and it's hierarchy of + parent objects, each have the desired roles. Please note: You + should strongly consider an alternative means for determining + that a given object is the desired item. Failing that, you should + include only enough of the hierarchy to make the determination. + If the developer of the application you are providing access to + does so much as add an Adjustment to reposition a widget, this + method can fail. You have been warned. + + Arguments: + - obj: the accessible object to check. + - rolesList: the list of desired roles for the components and the + hierarchy of its parents. + + Returns True if all roles match. + """ + + current = obj + for role in rolesList: + if current is None: + return False + + if not isinstance(role, list): + role = [role] + + if isinstance(role[0], str): + current_role = AXObject.get_role_name(current) + else: + current_role = AXObject.get_role(current) + + if current_role not in role: + return False + + current = AXObject.get_parent_checked(current) + + return True + + def inFindContainer(self, obj=None): + if obj is None: + obj = cthulhu_state.locusOfFocus + + if not AXUtilities.is_entry(obj): + return False + + return AXObject.find_ancestor(obj, AXUtilities.is_tool_bar) is not None + + def getFindResultsCount(self, root=None): + return "" + + def isAnchor(self, obj): + return False + + def isCode(self, obj): + return False + + def isCodeDescendant(self, obj): + return False + + def isDockedFrame(self, obj): + if not AXUtilities.is_frame(obj): + return False + + attrs = self.objectAttributes(obj) + return attrs.get('window-type') == 'dock' + + def isDesktop(self, obj): + if not AXUtilities.is_frame(obj): + return False + + attrs = self.objectAttributes(obj) + return attrs.get('is-desktop') == 'true' + + def isComboBoxWithToggleDescendant(self, obj): + return False + + def isToggleDescendantOfComboBox(self, obj): + return False + + def isTypeahead(self, obj): + return False + + def isOrDescendsFrom(self, obj, ancestor): + if obj == ancestor: + return True + + return AXObject.find_ancestor(obj, lambda x: x and x == ancestor) + + def isFunctionalDialog(self, obj): + """Returns True if the window is a functioning as a dialog. + This method should be subclassed by application scripts as + needed. + """ + + return False + + def isComment(self, obj): + return False + + def isContentDeletion(self, obj): + return False + + def isContentError(self, obj): + return False + + def isContentInsertion(self, obj): + return False + + def isContentMarked(self, obj): + return False + + def isContentSuggestion(self, obj): + return False + + def isInlineSuggestion(self, obj): + return False + + def isFirstItemInInlineContentSuggestion(self, obj): + return False + + def isLastItemInInlineContentSuggestion(self, obj): + return False + + def isEmpty(self, obj): + return False + + def isHidden(self, obj): + return False + + def isDPub(self, obj): + return False + + def isDPubAbstract(self, obj): + return False + + def isDPubAcknowledgments(self, obj): + return False + + def isDPubAfterword(self, obj): + return False + + def isDPubAppendix(self, obj): + return False + + def isDPubBibliography(self, obj): + return False + + def isDPubBacklink(self, obj): + return False + + def isDPubBiblioref(self, obj): + return False + + def isDPubChapter(self, obj): + return False + + def isDPubColophon(self, obj): + return False + + def isDPubConclusion(self, obj): + return False + + def isDPubCover(self, obj): + return False + + def isDPubCredit(self, obj): + return False + + def isDPubCredits(self, obj): + return False + + def isDPubDedication(self, obj): + return False + + def isDPubEndnote(self, obj): + return False + + def isDPubEndnotes(self, obj): + return False + + def isDPubEpigraph(self, obj): + return False + + def isDPubEpilogue(self, obj): + return False + + def isDPubErrata(self, obj): + return False + + def isDPubExample(self, obj): + return False + + def isDPubFootnote(self, obj): + return False + + def isDPubForeword(self, obj): + return False + + def isDPubGlossary(self, obj): + return False + + def isDPubGlossref(self, obj): + return False + + def isDPubIndex(self, obj): + return False + + def isDPubIntroduction(self, obj): + return False + + def isDPubPagelist(self, obj): + return False + + def isDPubPagebreak(self, obj): + return False + + def isDPubPart(self, obj): + return False + + def isDPubPreface(self, obj): + return False + + def isDPubPrologue(self, obj): + return False + + def isDPubPullquote(self, obj): + return False + + def isDPubQna(self, obj): + return False + + def isDPubSubtitle(self, obj): + return False + + def isDPubToc(self, obj): + return False + + def isFeed(self, obj): + return False + + def isFeedArticle(self, obj): + return False + + def isFigure(self, obj): + return False + + def isGrid(self, obj): + return False + + def isGridCell(self, obj): + return False + + def isLandmark(self, obj): + return False + + def isLandmarkWithoutType(self, obj): + return False + + def isLandmarkBanner(self, obj): + return False + + def isLandmarkComplementary(self, obj): + return False + + def isLandmarkContentInfo(self, obj): + return False + + def isLandmarkForm(self, obj): + return False + + def isLandmarkMain(self, obj): + return False + + def isLandmarkNavigation(self, obj): + return False + + def isDPubNoteref(self, obj): + return False + + def isLandmarkRegion(self, obj): + return False + + def isLandmarkSearch(self, obj): + return False + + def isSVG(self, obj): + return False + + def speakMathSymbolNames(self, obj=None): + return False + + def isInMath(self): + return False + + def isMath(self, obj): + return False + + def isMathLayoutOnly(self, obj): + return False + + def isMathMultiline(self, obj): + return False + + def isMathEnclosed(self, obj): + return False + + def isMathFenced(self, obj): + return False + + def isMathFractionWithoutBar(self, obj): + return False + + def isMathPhantom(self, obj): + return False + + def isMathMultiScript(self, obj): + return False + + def isMathSubOrSuperScript(self, obj): + return False + + def isMathUnderOrOverScript(self, obj): + return False + + def isMathSquareRoot(self, obj): + return False + + def isMathTable(self, obj): + return False + + def isMathTableRow(self, obj): + return False + + def isMathTableCell(self, obj): + return False + + def isMathToken(self, obj): + return False + + def isMathTopLevel(self, obj): + return False + + def getMathDenominator(self, obj): + return None + + def getMathNumerator(self, obj): + return None + + def getMathRootBase(self, obj): + return None + + def getMathRootIndex(self, obj): + return None + + def getMathScriptBase(self, obj): + return None + + def getMathScriptSubscript(self, obj): + return None + + def getMathScriptSuperscript(self, obj): + return None + + def getMathScriptUnderscript(self, obj): + return None + + def getMathScriptOverscript(self, obj): + return None + + def getMathPrescripts(self, obj): + return [] + + def getMathPostscripts(self, obj): + return [] + + def getMathEnclosures(self, obj): + return [] + + def getMathFencedSeparators(self, obj): + return [''] + + def getMathFences(self, obj): + return ['', ''] + + def getMathNestingLevel(self, obj, test=None): + return 0 + + def getLandmarkTypes(self): + return ["banner", + "complementary", + "contentinfo", + "doc-acknowledgments", + "doc-afterword", + "doc-appendix", + "doc-bibliography", + "doc-chapter", + "doc-conclusion", + "doc-credits", + "doc-endnotes", + "doc-epilogue", + "doc-errata", + "doc-foreword", + "doc-glossary", + "doc-index", + "doc-introduction", + "doc-pagelist", + "doc-part", + "doc-preface", + "doc-prologue", + "doc-toc", + "form", + "main", + "navigation", + "region", + "search"] + + def isProgressBar(self, obj): + if not AXUtilities.is_progress_bar(obj): + return False + + try: + value = obj.queryValue() + except NotImplementedError: + tokens = ["SCRIPT UTILITIES:", obj, "doesn't implement AtspiValue"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting value for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + else: + try: + if value.maximumValue == value.minimumValue: + tokens = ["SCRIPT UTILITIES:", obj, "is busy indicator"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + except Exception: + tokens = ["SCRIPT UTILITIES:", obj, "is either busy indicator or broken"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + def isProgressBarUpdate(self, obj): + if not _settingsManager.getSetting('speakProgressBarUpdates') \ + and not _settingsManager.getSetting('brailleProgressBarUpdates') \ + and not _settingsManager.getSetting('beepProgressBarUpdates'): + return False, "Updates not enabled" + + if not self.isProgressBar(obj): + return False, "Is not progress bar" + + if self.hasNoSize(obj): + return False, "Has no size" + + if _settingsManager.getSetting('ignoreStatusBarProgressBars'): + if AXObject.find_ancestor(obj, AXUtilities.is_status_bar): + return False, "Is status bar descendant" + + verbosity = _settingsManager.getSetting('progressBarVerbosity') + if verbosity == settings.PROGRESS_BAR_ALL: + return True, "Verbosity is all" + + if verbosity == settings.PROGRESS_BAR_WINDOW: + topLevel = self.topLevelObject(obj) + if topLevel == cthulhu_state.activeWindow: + return True, "Verbosity is window" + return False, f"Window {topLevel} is not {cthulhu_state.activeWindow}" + + if verbosity == settings.PROGRESS_BAR_APPLICATION: + app = AXObject.get_application(obj) + if app == cthulhu_state.activeScript.app: + return True, "Verbosity is app" + return False, f"App {app} is not {cthulhu_state.activeScript.app}" + + return True, "Not handled by any other case" + + def getValueAsPercent(self, obj): + try: + value = obj.queryValue() + minval, val, maxval = value.minimumValue, value.currentValue, value.maximumValue + except NotImplementedError: + tokens = ["SCRIPT UTILITIES:", obj, "doesn't implement AtspiValue"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting value for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if AXUtilities.is_indeterminate(obj): + tokens = ["SCRIPT UTILITIES:", obj, "has state indeterminate and value of", val] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if val <= 0: + return None + + if maxval == minval == val: + if 1 <= val <= 100: + return int(val) + return None + + return int((val / (maxval - minval)) * 100) + + def isBlockquote(self, obj): + return AXUtilities.is_block_quote(obj) + + def isDescriptionList(self, obj): + return AXUtilities.is_description_list(obj) + + def isDescriptionListTerm(self, obj): + return AXUtilities.is_description_term(obj) + + def isDescriptionListDescription(self, obj): + return AXUtilities.is_description_value(obj) + + def descriptionListTerms(self, obj): + if not self.isDescriptionList(obj): + return [] + + _include = self.isDescriptionListTerm + _exclude = self.isDescriptionList + return self.findAllDescendants(obj, _include, _exclude) + + def isDocumentList(self, obj): + if AXObject.get_role(obj) not in [Atspi.Role.LIST, Atspi.Role.DESCRIPTION_LIST]: + return False + return AXObject.find_ancestor(obj, AXUtilities.is_document) is not None + + def isDocumentPanel(self, obj): + if not AXUtilities.is_panel(obj): + return False + return AXObject.find_ancestor(obj, AXUtilities.is_document) is not None + + def isDocument(self, obj): + return AXUtilities.is_document(obj) + + def inDocumentContent(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + return self.getDocumentForObject(obj) is not None + + def activeDocument(self, window=None): + return self.getTopLevelDocumentForObject(cthulhu_state.locusOfFocus) + + def isTopLevelDocument(self, obj): + return self.isDocument(obj) and not AXObject.find_ancestor(obj, self.isDocument) + + def getTopLevelDocumentForObject(self, obj): + if self.isTopLevelDocument(obj): + return obj + + return AXObject.find_ancestor(obj, self.isTopLevelDocument) + + def getDocumentForObject(self, obj): + if not obj: + return None + + if self.isDocument(obj): + return obj + + return AXObject.find_ancestor(obj, self.isDocument) + + def getModalDialog(self, obj): + if not obj: + return False + + if AXUtilities.is_modal_dialog(obj): + return obj + + return AXObject.find_ancestor(obj, AXUtilities.is_modal_dialog) + + def isModalDialogDescendant(self, obj): + if not obj: + return False + + return self.getModalDialog(obj) is not None + + def getTable(self, obj): + if not obj: + return None + + def isTable(x): + if AXUtilities.is_table(x) or AXUtilities.is_tree_table(x) or AXUtilities.is_tree(x): + return AXObject.supports_table(x) + return False + + if isTable(obj): + return obj + + return AXObject.find_ancestor(obj, isTable) + + def isTextDocumentTable(self, obj): + if not AXUtilities.is_table(obj): + return False + + doc = self.getDocumentForObject(obj) + return doc is not None and not AXUtilities.is_document_spreadsheet(doc) + + def isGUITable(self, obj): + return AXUtilities.is_table(obj) and self.getDocumentForObject(obj) is None + + def isSpreadSheetTable(self, obj): + if not (AXUtilities.is_table(obj) and AXObject.supports_table(obj)): + return False + + doc = self.getDocumentForObject(obj) + if doc is None: + return False + if AXUtilities.is_document_spreadsheet(doc): + return True + + return obj.queryTable().nRows > 65536 + + def isTextDocumentCell(self, obj): + if not AXUtilities.is_table_cell_or_header(obj): + return False + return AXObject.find_ancestor(obj, self.isTextDocumentTable) + + def isSpreadSheetCell(self, obj): + if not AXUtilities.is_table_cell_or_header(obj): + return False + return AXObject.find_ancestor(obj, self.isSpreadSheetTable) + + def cellColumnChanged(self, cell): + row, column = self.coordinatesForCell(cell) + if column == -1: + return False + + lastColumn = self._script.pointOfReference.get("lastColumn") + return column != lastColumn + + def cellRowChanged(self, cell): + row, column = self.coordinatesForCell(cell) + if row == -1: + return False + + lastRow = self._script.pointOfReference.get("lastRow") + return row != lastRow + + def shouldReadFullRow(self, obj): + if self._script.inSayAll(): + return False + + if not self.cellRowChanged(obj): + return False + + table = self.getTable(obj) + if not table: + return False + + if not self.getDocumentForObject(table): + return _settingsManager.getSetting('readFullRowInGUITable') + + if self.isSpreadSheetTable(table): + return _settingsManager.getSetting('readFullRowInSpreadSheet') + + return _settingsManager.getSetting('readFullRowInDocumentTable') + + def isSorted(self, obj): + return False + + def isAscending(self, obj): + return False + + def isDescending(self, obj): + return False + + def getSortOrderDescription(self, obj, includeName=False): + if not (obj and self.isSorted(obj)): + return "" + + if self.isAscending(obj): + result = object_properties.SORT_ORDER_ASCENDING + elif self.isDescending(obj): + result = object_properties.SORT_ORDER_DESCENDING + else: + result = object_properties.SORT_ORDER_OTHER + + if includeName and AXObject.get_name(obj): + result = f"{AXObject.get_name(obj)}. {result}" + + return result + + def isFocusableLabel(self, obj): + return AXUtilities.is_label(obj) and AXUtilities.is_focusable(obj) + + def isNonFocusableList(self, obj): + return AXUtilities.is_list(obj) and not AXUtilities.is_focusable(obj) + + def isStatusBarNotification(self, obj): + if not AXUtilities.is_notification(obj): + return False + return AXObject.find_ancestor(obj, AXUtilities.is_status_bar) is not None + + def getNotificationContent(self, obj): + if not AXUtilities.is_notification(obj): + return "" + + tokens = [] + name = AXObject.get_name(obj) + if name: + tokens.append(name) + text = self.expandEOCs(obj) + if text and text not in tokens: + tokens.append(text) + else: + labels = " ".join(map(self.displayedText, self.unrelatedLabels(obj, False, 1))) + if labels and labels not in tokens: + tokens.append(labels) + + if not tokens: + description = AXObject.get_description(obj) + if description: + tokens.append(description) + + return " ".join(tokens) + + def isTreeDescendant(self, obj): + if obj is None: + return False + + if AXUtilities.is_tree_item(obj): + return True + + return AXObject.find_ancestor(obj, AXUtilities.is_tree_or_tree_table) is not None + + def isLayoutOnly(self, obj): + """Returns True if the given object is a container which has + no presentable information (label, name, displayed text, etc.).""" + + layoutOnly = False + + if AXObject.is_dead(obj) or self.isZombie(obj): + return True + + attrs = self.objectAttributes(obj) + role = AXObject.get_role(obj) + parentRole = AXObject.get_role(AXObject.get_parent(obj)) + firstChild = AXObject.get_child(obj, 0) + + topLevelRoles = self._topLevelRoles() + ignorePanelParent = [Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.LIST_ITEM, + Atspi.Role.TREE_ITEM] + + if role == Atspi.Role.TABLE and attrs.get('layout-guess') != 'true': + try: + table = obj.queryTable() + except NotImplementedError: + tokens = ["SCRIPT UTILITIES: Table", obj, "does not implement table interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + layoutOnly = True + except Exception as error: + tokens = ["SCRIPT UTILITIES: Error querying table interface of", obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + layoutOnly = True + else: + if not (table.nRows and table.nColumns): + layoutOnly = not AXUtilities.is_focused(obj) + elif attrs.get('xml-roles') == 'table' or attrs.get('tag') == 'table': + layoutOnly = False + elif not (AXObject.get_name(obj) or self.displayedLabel(obj)): + layoutOnly = not (table.getColumnHeader(0) or table.getRowHeader(0)) + elif role == Atspi.Role.TABLE_CELL and AXObject.get_child_count(obj): + if parentRole == Atspi.Role.TREE_TABLE: + layoutOnly = not AXObject.get_name(obj) + elif AXUtilities.is_table_cell(firstChild): + layoutOnly = True + elif parentRole == Atspi.Role.TABLE: + layoutOnly = self.isLayoutOnly(AXObject.get_parent(obj)) + elif role == Atspi.Role.SECTION: + layoutOnly = not self.isBlockquote(obj) + elif role == Atspi.Role.BLOCK_QUOTE: + layoutOnly = False + elif role == Atspi.Role.FILLER: + layoutOnly = True + elif role == Atspi.Role.SCROLL_PANE: + layoutOnly = True + elif role == Atspi.Role.LAYERED_PANE: + layoutOnly = self.isDesktop(self.topLevelObject(obj)) + elif role == Atspi.Role.AUTOCOMPLETE: + layoutOnly = True + elif role in [Atspi.Role.TEAROFF_MENU_ITEM, Atspi.Role.SEPARATOR]: + layoutOnly = True + elif role in [Atspi.Role.LIST_BOX, Atspi.Role.TREE_TABLE]: + layoutOnly = False + elif role in topLevelRoles: + layoutOnly = False + elif role == Atspi.Role.MENU: + layoutOnly = parentRole == Atspi.Role.COMBO_BOX + elif role == Atspi.Role.COMBO_BOX: + layoutOnly = False + elif role == Atspi.Role.LIST: + layoutOnly = False + elif role == Atspi.Role.FORM: + layoutOnly = False + elif role in [Atspi.Role.PUSH_BUTTON, Atspi.Role.TOGGLE_BUTTON]: + layoutOnly = False + elif role in [Atspi.Role.TEXT, Atspi.Role.PASSWORD_TEXT, Atspi.Role.ENTRY]: + layoutOnly = False + elif role == Atspi.Role.LIST_ITEM and parentRole == Atspi.Role.LIST_BOX: + layoutOnly = False + elif role in [Atspi.Role.REDUNDANT_OBJECT, Atspi.Role.UNKNOWN]: + layoutOnly = True + elif self.isTableRow(obj): + layoutOnly = not (AXUtilities.is_focusable(obj) or AXUtilities.is_selectable(obj)) + elif role == Atspi.Role.PANEL and AXObject.get_role(firstChild) in ignorePanelParent: + layoutOnly = True + elif role == Atspi.Role.PANEL \ + and AXObject.has_same_non_empty_name(obj, AXObject.get_application(obj)): + layoutOnly = True + elif AXObject.get_child_count(obj) == 1 \ + and AXObject.has_same_non_empty_name(obj, firstChild): + layoutOnly = True + elif self.isHidden(obj): + layoutOnly = True + else: + if not (self.displayedText(obj) or self.displayedLabel(obj)): + layoutOnly = True + + if layoutOnly: + tokens = ["SCRIPT UTILITIES:", obj, "is deemed to be layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return layoutOnly + + @staticmethod + def isInActiveApp(obj): + """Returns True if the given object is from the same application that + currently has keyboard focus. + + Arguments: + - obj: an Accessible object + """ + + if not obj or not cthulhu_state.locusOfFocus: + return False + + return AXObject.get_application(cthulhu_state.locusOfFocus) == AXObject.get_application(obj) + + def isLink(self, obj): + """Returns True if obj is a link.""" + + return AXUtilities.is_link(obj) + + def isReadOnlyTextArea(self, obj): + """Returns True if obj is a text entry area that is read only.""" + + if not self.isTextArea(obj): + return False + + if AXUtilities.is_read_only(obj): + return True + + return AXUtilities.is_focusable(obj) and not AXUtilities.is_editable(obj) + + def isSwitch(self, obj): + return False + + def getObjectFromPath(self, path): + start = self._script.app + rv = None + for p in path: + if p == -1: + continue + try: + start = start[p] + except Exception: + break + else: + rv = start + + return rv + + def _hasSamePath(self, obj1, obj2): + path1 = AXObject.get_path(obj1) + path2 = AXObject.get_path(obj2) + if len(path1) != len(path2): + return False + + if not (path1 and path2): + return False + + # The first item in all paths, even valid ones, is -1. + path1 = path1[1:] + path2 = path2[1:] + + # If the object is being destroyed and the replacement is too, which + # sadly can happen in at least Firefox, both will have an index of -1. + # If the rest of the paths are valid and match, it's probably ok. + if path1[-1] == -1 and path2[-1] == -1: + path1 = path1[:-1] + path2 = path2[:-1] + + # If both have invalid child indices, all bets are off. + if path1.count(-1) and path2.count(-1): + return False + + try: + index = path1.index(-1) + except ValueError: + try: + index = path2.index(-1) + except ValueError: + index = len(path2) + + return path1[0:index] == path2[0:index] + + def isSameObject(self, obj1, obj2, comparePaths=False, ignoreNames=False, + ignoreDescriptions=True): + if obj1 == obj2: + return True + + if obj1 is None or obj2 is None: + return False + + if not AXUtilities.have_same_role(obj1, obj2): + return False + + if not ignoreNames and AXObject.get_name(obj1) != AXObject.get_name(obj2): + return False + + if not ignoreDescriptions \ + and AXObject.get_description(obj1) != AXObject.get_description(obj2): + return False + + if comparePaths and self._hasSamePath(obj1, obj2): + return True + + try: + # Comparing the extents of objects which claim to be different + # addresses both managed descendants and implementations which + # recreate accessibles for the same widget. + extents1 = \ + obj1.queryComponent().getExtents(Atspi.CoordType.WINDOW) + extents2 = \ + obj2.queryComponent().getExtents(Atspi.CoordType.WINDOW) + + # Objects which claim to be different and which are in different + # locations are almost certainly not recreated objects. + if extents1 != extents2: + return False + + # Objects which claim to have the same role, the same name, and + # the same size and position are highly likely to be the same + # functional object -- if they have valid, on-screen extents. + if extents1.x >= 0 and extents1.y >= 0 and extents1.width > 0 \ + and extents1.height > 0: + return True + except Exception as error: + tokens = ["SCRIPT UTILITIES: Exception in isSameObject (", + obj1, "vs", obj2, "):", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return False + + def isTextArea(self, obj): + """Returns True if obj is a GUI component that is for entering text. + + Arguments: + - obj: an accessible + """ + + if self.isLink(obj): + return False + + # TODO - JD: This might have been enough way back when, but additional + # checks are needed now. + return AXUtilities.is_text_input(obj) \ + or AXUtilities.is_text(obj) \ + or AXUtilities.is_paragraph(obj) + + def labelsForObject(self, obj): + """Return a list of the labels for this object.""" + + def isNotAncestor(acc): + return not AXObject.find_ancestor(obj, lambda x: x == acc) + + result = AXObject.get_relation_targets(obj, Atspi.RelationType.LABELLED_BY) + return list(filter(isNotAncestor, result)) + + def linkBasenameToName(self, obj): + basename = self.linkBasename(obj) + if not basename: + return "" + + basename = re.sub(r"[-_]", " ", basename) + tokens = basename.split() + for token in tokens: + if not token.isalpha(): + return "" + + return basename + + @staticmethod + def linkBasename(obj): + """Returns the relevant information from the URI. The idea is + to attempt to strip off all prefix and suffix, much like the + basename command in a shell.""" + + basename = None + + try: + hyperlink = obj.queryHyperlink() + except Exception: + pass + else: + uri = hyperlink.getURI(0) + if uri and len(uri): + # Sometimes the URI is an expression that includes a URL. + # Currently that can be found at the bottom of safeway.com. + # It can also be seen in the backwards.html test file. + # + expression = uri.split(',') + if len(expression) > 1: + for item in expression: + if item.find('://') >=0: + if not item[0].isalnum(): + item = item[1:-1] + if not item[-1].isalnum(): + item = item[0:-2] + uri = item + break + + # We're assuming that there IS a base name to be had. + # What if there's not? See backwards.html. + # + uri = uri.split('://')[-1] + if not uri: + return basename + + # Get the last thing after all the /'s, unless it ends + # in a /. If it ends in a /, we'll look to the stuff + # before the ending /. + # + if uri[-1] == "/": + basename = uri[0:-1] + basename = basename.split('/')[-1] + elif not uri.count("/"): + basename = uri + else: + basename = uri.split('/')[-1] + if basename.startswith("index"): + basename = uri.split('/')[-2] + + # Now, try to strip off the suffixes. + # + basename = basename.split('.')[0] + basename = basename.split('?')[0] + basename = basename.split('#')[0] + basename = basename.split('%')[0] + + return basename + + @staticmethod + def linkIndex(obj, characterIndex): + """A brute force method to see if an offset is a link. This + is provided because not all Accessible Hypertext implementations + properly support the getLinkIndex method. Returns an index of + 0 or greater of the characterIndex is on a hyperlink. + + Arguments: + -obj: the object with the Accessible Hypertext specialization + -characterIndex: the text position to check + """ + + if not obj: + return -1 + + try: + obj.queryText() + except NotImplementedError: + return -1 + + try: + hypertext = obj.queryHypertext() + except NotImplementedError: + return -1 + + for i in range(hypertext.getNLinks()): + link = hypertext.getLink(i) + if (characterIndex >= link.startIndex) \ + and (characterIndex <= link.endIndex): + return i + + return -1 + + def nestingLevel(self, obj): + """Determines the nesting level of this object. + + Arguments: + -obj: the Accessible object + """ + + if obj is None: + return 0 + + try: + return self._script.generatorCache[self.NESTING_LEVEL][obj] + except Exception: + if self.NESTING_LEVEL not in self._script.generatorCache: + self._script.generatorCache[self.NESTING_LEVEL] = {} + + def pred(x): + if self.isBlockquote(obj): + return self.isBlockquote(x) + if AXUtilities.is_list_item(obj): + return AXUtilities.is_list(AXObject.get_parent(x)) + return AXUtilities.have_same_role(obj, x) + + ancestors = [] + ancestor = AXObject.find_ancestor(obj, pred) + while ancestor: + ancestors.append(ancestor) + ancestor = AXObject.find_ancestor(ancestor, pred) + + nestingLevel = len(ancestors) + self._script.generatorCache[self.NESTING_LEVEL][obj] = nestingLevel + return self._script.generatorCache[self.NESTING_LEVEL][obj] + + def nodeLevel(self, obj): + """Determines the node level of this object if it is in a tree + relation, with 0 being the top level node. If this object is + not in a tree relation, then -1 will be returned. + + Arguments: + -obj: the Accessible object + """ + + if not self.isTreeDescendant(obj): + return -1 + + try: + return self._script.generatorCache[self.NODE_LEVEL][obj] + except Exception: + if self.NODE_LEVEL not in self._script.generatorCache: + self._script.generatorCache[self.NODE_LEVEL] = {} + + nodes = [] + node = obj + done = False + while not done: + relation = AXObject.get_relation(node, Atspi.RelationType.NODE_CHILD_OF) + node = None + if relation: + node = relation.get_target(0) + + # We want to avoid situations where something gives us an + # infinite cycle of nodes. Bon Echo has been seen to do + # this (see bug 351847). + if nodes.count(node): + tokens = ["SCRIPT UTILITIES:", node, "is already in the list of nodes for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + done = True + if len(nodes) > 100: + tokens = ["SCRIPT UTILITIES: More than 100 nodes found for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + done = True + elif node: + nodes.append(node) + else: + done = True + + self._script.generatorCache[self.NODE_LEVEL][obj] = len(nodes) - 1 + return self._script.generatorCache[self.NODE_LEVEL][obj] + + def isOnScreen(self, obj, boundingbox=None): + if AXObject.is_dead(obj): + return False + + if self.isHidden(obj): + return False + + if not self.isShowingAndVisible(obj): + tokens = ["SCRIPT UTILITIES:", obj, "is not showing and visible"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + try: + box = obj.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["SCRIPT UTILITIES: Extents for", obj, "are:", box] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if box.x > 10000 or box.y > 10000: + tokens = ["SCRIPT UTILITIES:", obj, "seems to have bogus coordinates"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if box.x < 0 and box.y < 0 and tuple(box) != (-1, -1, -1, -1): + tokens = ["SCRIPT UTILITIES:", obj, "has negative coordinates"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if not (box.width or box.height): + if not AXObject.get_child_count(obj): + tokens = ["SCRIPT UTILITIES:", obj, "has no size and no children"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + if AXUtilities.is_menu(obj): + tokens = ["SCRIPT UTILITIES:", obj, "has no size"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + if boundingbox is None or not self._boundsIncludeChildren(AXObject.get_parent(obj)): + return True + + if not self.containsRegion(box, boundingbox) and tuple(box) != (-1, -1, -1, -1): + tokens = ["SCRIPT UTILITIES:", obj, box, "not in", boundingbox] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + def selectedMenuBarMenu(self, menubar): + if not AXUtilities.is_menu_bar(menubar): + return None + + if AXObject.supports_selection(menubar): + selected = self.selectedChildren(menubar) + if selected: + return selected[0] + return None + + for menu in AXObject.iter_children(menubar): + AXObject.clear_cache(menu) + if AXUtilities.is_expanded(menu) or AXUtilities.is_selected(menu): + return menu + + return None + + def isInOpenMenuBarMenu(self, obj): + if obj is None: + return False + + menubar = AXObject.find_ancestor(obj, AXUtilities.is_menu_bar) + if menubar is None: + return False + + selectedMenu = self._selectedMenuBarMenu.get(hash(menubar)) + if selectedMenu is None: + selectedMenu = self.selectedMenuBarMenu(menubar) + + if selectedMenu is None: + return False + + def inSelectedMenu(x): + return x == selectedMenu + + if inSelectedMenu(obj): + return True + + return AXObject.find_ancestor(obj, inSelectedMenu) is not None + + def isStaticTextLeaf(self, obj): + return False + + def isListItemMarker(self, obj): + return False + + def hasPresentableText(self, obj): + if self.isStaticTextLeaf(obj): + return False + + if not AXObject.supports_text(obj): + return False + + return bool(re.search(r"\w+", obj.queryText().getText(0, -1))) + + def getOnScreenObjects(self, root, extents=None): + if not self.isOnScreen(root, extents): + return [] + + if AXObject.get_role(root) == Atspi.Role.INVALID: + return [] + + if AXUtilities.is_button(root) or AXUtilities.is_combo_box(root): + return [root] + + if AXUtilities.is_menu_bar(root): + self._selectedMenuBarMenu[hash(root)] = self.selectedMenuBarMenu(root) + + if AXUtilities.is_menu_bar(AXObject.get_parent(root)) \ + and not self.isInOpenMenuBarMenu(root): + return [root] + + if AXUtilities.is_filler(root) and not AXObject.get_child_count(root): + tokens = ["SCRIPT UTILITIES:", root, "is empty filler. Clearing cache."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + AXObject.clear_cache(root, recursive=True) + tokens = ["SCRIPT UTILITIES:", root, "now reports", + AXObject.get_child_count(root), "children"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if extents is None: + try: + component = root.queryComponent() + extents = component.getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting extents of", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + extents = 0, 0, 0, 0 + + if AXObject.supports_table(root) and AXObject.supports_selection(root): + visibleCells = self.getVisibleTableCells(root) + if visibleCells: + return visibleCells + + objects = [] + hasNameOrDesc = AXObject.get_name(root) or AXObject.get_description(root) + if hasNameOrDesc and (AXUtilities.is_page_tab(root) or AXUtilities.is_image(root)): + objects.append(root) + elif self.hasPresentableText(root): + objects.append(root) + + def pred(x): + return x is not None and not self.isStaticTextLeaf(x) + + for child in AXObject.iter_children(root, pred): + objects.extend(self.getOnScreenObjects(child, extents)) + + if AXUtilities.is_menu_bar(root): + self._selectedMenuBarMenu[hash(root)] = None + + if objects: + return objects + + if AXUtilities.is_label(root) and not hasNameOrDesc and not self.queryNonEmptyText(root): + return [] + + containers = [Atspi.Role.CANVAS, + Atspi.Role.FILLER, + Atspi.Role.IMAGE, + Atspi.Role.LINK, + Atspi.Role.LIST_BOX, + Atspi.Role.PANEL, + Atspi.Role.SECTION, + Atspi.Role.SCROLL_PANE, + Atspi.Role.VIEWPORT] + if AXObject.get_role(root) in containers and not hasNameOrDesc: + return [] + + return [root] + + @staticmethod + def isTableRow(obj): + """Determines if obj is a table row -- real or functionally.""" + + childCount = AXObject.get_child_count(obj) + if not childCount: + return False + + if AXObject.get_parent(obj) is None: + return False + + if AXUtilities.is_table_row(obj): + return True + + if AXUtilities.is_table_cell_or_header(obj): + return False + + if not AXUtilities.is_table(AXObject.get_parent(obj)): + return False + + cells = [x for x in AXObject.iter_children(obj, AXUtilities.is_table_cell_or_header)] + if len(cells) == childCount: + return True + + return False + + def realActiveAncestor(self, obj): + if AXUtilities.is_focused(obj): + return obj + + def pred(x): + return AXUtilities.is_table_cell_or_header(x) or AXUtilities.is_list_item(x) + + ancestor = AXObject.find_ancestor(obj, pred) + if ancestor is not None \ + and not self._script.utilities.isLayoutOnly(AXObject.get_parent(ancestor)): + obj = ancestor + + return obj + + def realActiveDescendant(self, obj): + """Given an object that should be a child of an object that + manages its descendants, return the child that is the real + active descendant carrying useful information. + + Arguments: + - obj: an object that should be a child of an object that + manages its descendants. + """ + + if AXObject.is_dead(obj): + return None + + if not AXUtilities.is_table_cell(obj): + return obj + + if AXObject.get_name(obj): + return obj + + def pred(x): + return x and not self.isStaticTextLeaf(x) and self.displayedText(x).strip() + + child = AXObject.find_descendant(obj, pred) + if child is not None: + return child + + return obj + + def isStatusBarDescendant(self, obj): + if obj is None: + return False + + return AXObject.find_ancestor(obj, AXUtilities.is_status_bar) is not None + + def statusBarItems(self, obj): + if not AXUtilities.is_status_bar(obj): + return [] + + start = time.time() + items = self._script.pointOfReference.get('statusBarItems') + if not items: + + def include(x): + return not AXUtilities.is_status_bar(x) + + items = list(filter(include, self.getOnScreenObjects(obj))) + self._script.pointOfReference['statusBarItems'] = items + + end = time.time() + msg = f"SCRIPT UTILITIES: Time getting status bar items: {end - start:.4f}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + return items + + def infoBar(self, root): + return None + + def _topLevelRoles(self): + roles = [Atspi.Role.DIALOG, + Atspi.Role.FILE_CHOOSER, + Atspi.Role.FRAME, + Atspi.Role.WINDOW] + if self._treatAlertsAsDialogs(): + roles.append(Atspi.Role.ALERT) + return roles + + def _locusOfFocusIsTopLevelObject(self): + if not cthulhu_state.locusOfFocus: + return False + + rv = cthulhu_state.locusOfFocus == self.topLevelObject(cthulhu_state.locusOfFocus) + tokens = ["SCRIPT UTILITIES:", cthulhu_state.locusOfFocus, "is top-level object:", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def _findWindowWithDescendant(self, child): + """Searches each frame/window/dialog of an application to find the one + which contains child. This is extremely non-performant and should only + be used to work around broken accessibility trees where topLevelObject + fails.""" + + app = AXObject.get_application(child) + if app is None: + return None + + for i in range(AXObject.get_child_count(app)): + window = AXObject.get_child(app, i) + if AXObject.find_descendant(window, lambda x: x == child) is not None: + tokens = ["SCRIPT UTILITIES:", window, "contains", child] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return window + + tokens = ["SCRIPT UTILITIES:", window, "does not contain", child] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return None + + def _isTopLevelObject(self, obj): + return AXObject.get_role(obj) in self._topLevelRoles() \ + and AXObject.get_role(AXObject.get_parent(obj)) == Atspi.Role.APPLICATION + + def topLevelObject(self, obj, useFallbackSearch=False): + """Returns the top-level object (frame, dialog ...) containing obj, + or None if obj is not inside a top-level object. + + Arguments: + - obj: the Accessible object + """ + + if self._isTopLevelObject(obj): + rv = obj + else: + rv = AXObject.find_ancestor(obj, self._isTopLevelObject) + + tokens = ["SCRIPT UTILITIES:", rv, "is top-level object for:", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if rv is None and useFallbackSearch: + msg = "SCRIPT UTILITIES: Attempting to find top-level object via fallback search" + debug.printMessage(debug.LEVEL_INFO, msg, True) + rv = self._findWindowWithDescendant(obj) + + return rv + + def topLevelObjectIsActiveAndCurrent(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + topLevel = self.topLevelObject(obj) + if not topLevel: + return False + + AXObject.clear_cache(topLevel) + if not AXUtilities.is_active(topLevel) or AXUtilities.is_defunct(topLevel): + return False + + if not self.isSameObject(topLevel, cthulhu_state.activeWindow): + return False + + return True + + @staticmethod + def onSameLine(obj1, obj2, delta=0): + """Determines if obj1 and obj2 are on the same line.""" + + try: + bbox1 = obj1.queryComponent().getExtents(Atspi.CoordType.SCREEN) + bbox2 = obj2.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except Exception: + return False + + center1 = bbox1.y + bbox1.height / 2 + center2 = bbox2.y + bbox2.height / 2 + + return abs(center1 - center2) <= delta + + @staticmethod + def pathComparison(path1, path2): + """Compares the two paths and returns -1, 0, or 1 to indicate if path1 + is before, the same, or after path2.""" + + if path1 == path2: + return 0 + + size = max(len(path1), len(path2)) + path1 = (path1 + [-1] * size)[:size] + path2 = (path2 + [-1] * size)[:size] + + for x in range(min(len(path1), len(path2))): + if path1[x] < path2[x]: + return -1 + if path1[x] > path2[x]: + return 1 + + return 0 + + @staticmethod + def sizeComparison(obj1, obj2): + try: + bbox = obj1.queryComponent().getExtents(Atspi.CoordType.SCREEN) + width1, height1 = bbox.width, bbox.height + except Exception: + width1, height1 = 0, 0 + + try: + bbox = obj2.queryComponent().getExtents(Atspi.CoordType.SCREEN) + width2, height2 = bbox.width, bbox.height + except Exception: + width2, height2 = 0, 0 + + return (width1 * height1) - (width2 * height2) + + @staticmethod + def spatialComparison(obj1, obj2): + """Compares the physical locations of obj1 and obj2 and returns -1, + 0, or 1 to indicate if obj1 physically is before, is in the same + place as, or is after obj2.""" + + try: + bbox = obj1.queryComponent().getExtents(Atspi.CoordType.SCREEN) + x1, y1 = bbox.x, bbox.y + except Exception: + x1, y1 = 0, 0 + + try: + bbox = obj2.queryComponent().getExtents(Atspi.CoordType.SCREEN) + x2, y2 = bbox.x, bbox.y + except Exception: + x2, y2 = 0, 0 + + rv = y1 - y2 or x1 - x2 + + # If the objects claim to have the same coordinates, there is either + # a horrible design crime or we've been given bogus extents. Fall back + # on the index in the parent. This is seen with GtkListBox items which + # had been scrolled off-screen. + if not rv and AXObject.get_parent(obj1) == AXObject.get_parent(obj2): + rv = AXObject.get_index_in_parent(obj1) - AXObject.get_index_in_parent(obj2) + + rv = max(rv, -1) + rv = min(rv, 1) + + return rv + + def getTextBoundingBox(self, obj, start, end): + try: + extents = obj.queryText().getRangeExtents(start, end, Atspi.CoordType.SCREEN) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting range extents of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1, 0, 0 + + return extents + + def getBoundingBox(self, obj): + try: + extents = obj.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting extents of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1, 0, 0 + + return extents.x, extents.y, extents.width, extents.height + + def hasNoSize(self, obj): + if not obj: + return False + + if AXUtilities.is_application(obj): + return False + + try: + extents = obj.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return not (extents.width and extents.height) + + def findAllDescendants(self, root, includeIf=None, excludeIf=None): + return AXObject.find_all_descendants(root, includeIf, excludeIf) + + def unrelatedLabels(self, root, onlyShowing=True, minimumWords=3): + """Returns a list containing all the unrelated (i.e., have no + relations to anything and are not a fundamental element of a + more atomic component like a combo box) labels under the given + root. Note that the labels must also be showing on the display. + + Arguments: + - root: the Accessible object to traverse + - onlyShowing: if True, only return labels with STATE_SHOWING + + Returns a list of unrelated labels under the given root. + """ + + if self._script.spellcheck and self._script.spellcheck.isCheckWindow(root): + return [] + + labelRoles = [Atspi.Role.LABEL, Atspi.Role.STATIC] + skipRoles = [Atspi.Role.COMBO_BOX, + Atspi.Role.LIST_BOX, + Atspi.Role.MENU, + Atspi.Role.MENU_BAR, + Atspi.Role.SCROLL_PANE, + Atspi.Role.SPLIT_PANE, + Atspi.Role.TABLE, + Atspi.Role.TREE, + Atspi.Role.TREE_TABLE] + + def _include(x): + if not (x and AXObject.get_role(x) in labelRoles): + return False + if AXObject.get_relations(x): + return False + if onlyShowing and not AXUtilities.is_showing(x): + return False + return True + + def _exclude(x): + if not x or AXObject.get_role(x) in skipRoles: + return True + if onlyShowing and not AXUtilities.is_showing(x): + return True + return False + + labels = self.findAllDescendants(root, _include, _exclude) + + rootName = AXObject.get_name(root) + + # Eliminate duplicates and things suspected to be labels for widgets + d = {} + for label in labels: + name = AXObject.get_name(label) or self.displayedText(label) + if name and name in [rootName, AXObject.get_name(AXObject.get_parent(label))]: + continue + if len(name.split()) < minimumWords: + continue + if rootName.find(name) >= 0: + continue + d[name] = label + labels = list(d.values()) + + return sorted(labels, key=functools.cmp_to_key(self.spatialComparison)) + + def _treatAlertsAsDialogs(self): + return True + + def unfocusedAlertAndDialogCount(self, obj): + """If the current application has one or more alert or dialog + windows and the currently focused window is not an alert or a dialog, + return a count of the number of alert and dialog windows, otherwise + return a count of zero. + + Arguments: + - obj: the Accessible object + + Returns the alert and dialog count. + """ + + roles = [Atspi.Role.DIALOG] + if self._treatAlertsAsDialogs(): + roles.append(Atspi.Role.ALERT) + + def isDialog(x): + return AXObject.get_role(x) in roles or self.isFunctionalDialog(x) + + dialogs = [x for x in AXObject.iter_children(AXObject.get_application(obj), isDialog)] + dialogs.extend([x for x in AXObject.iter_children(self.topLevelObject(obj), isDialog)]) + + def isPresentable(x): + return self.isShowingAndVisible(x) \ + and (AXObject.get_name(x) or AXObject.get_child_count(x)) + + def cannotBeActiveWindow(x): + return not self.canBeActiveWindow(x) + + presentable = list(filter(isPresentable, set(dialogs))) + unfocused = list(filter(cannotBeActiveWindow, presentable)) + return len(unfocused) + + def uri(self, obj): + """Return the URI for a given link object. + + Arguments: + - obj: the Accessible object. + """ + + try: + return obj.queryHyperlink().getURI(0) + except Exception: + return None + + ######################################################################### + # # + # Utilities for working with the accessible text interface # + # # + ######################################################################### + + @staticmethod + def adjustTextSelection(obj, offset): + """Adjusts the end point of a text selection + + Arguments: + - obj: the Accessible object. + - offset: the new end point - can be to the left or to the right + depending on the direction of selection + """ + + try: + text = obj.queryText() + except Exception: + return + + if text.getNSelections() <= 0: + caretOffset = text.caretOffset + startOffset = min(offset, caretOffset) + endOffset = max(offset, caretOffset) + text.addSelection(startOffset, endOffset) + else: + startOffset, endOffset = text.getSelection(0) + if offset < startOffset: + startOffset = offset + else: + endOffset = offset + text.setSelection(0, startOffset, endOffset) + + def findPreviousObject(self, obj): + """Finds the object before this one.""" + + if not obj or self.isZombie(obj): + return None + + relation = AXObject.get_relation(obj, Atspi.RelationType.FLOWS_FROM) + if relation: + return relation.get_target(0) + + return AXObject.get_previous_object(obj) + + def findNextObject(self, obj): + """Finds the object after this one.""" + + if not obj or self.isZombie(obj): + return None + + relation = AXObject.get_relation(obj, Atspi.RelationType.FLOWS_TO) + if relation: + return relation.get_target(0) + + return AXObject.get_next_object(obj) + + def allSelectedText(self, obj): + """Get all the text applicable text selections for the given object. + including any previous or next text objects that also have + selected text and add in their text contents. + + Arguments: + - obj: the text object to start extracting the selected text from. + + Returns: all the selected text contents plus the start and end + offsets within the text for the given object. + """ + + textContents, startOffset, endOffset = self.selectedText(obj) + if textContents and self._script.pointOfReference.get('entireDocumentSelected'): + return textContents, startOffset, endOffset + + if self.isSpreadSheetCell(obj): + return textContents, startOffset, endOffset + + prevObj = self.findPreviousObject(obj) + while prevObj: + if self.queryNonEmptyText(prevObj): + selection, start, end = self.selectedText(prevObj) + if not selection: + break + textContents = f"{selection} {textContents}" + prevObj = self.findPreviousObject(prevObj) + + nextObj = self.findNextObject(obj) + while nextObj: + if self.queryNonEmptyText(nextObj): + selection, start, end = self.selectedText(nextObj) + if not selection: + break + textContents = f"{textContents} {selection}" + nextObj = self.findNextObject(nextObj) + + return textContents, startOffset, endOffset + + @staticmethod + def allTextSelections(obj): + """Get a list of text selections in the given accessible object, + equivalent to getNSelections()*texti.getSelection() + + Arguments: + - obj: An accessible. + + Returns list of start and end offsets for multiple selections, or an + empty list if nothing is selected or if the accessible does not support + the text interface. + """ + + try: + text = obj.queryText() + except Exception: + return [] + + rv = [] + try: + nSelections = text.getNSelections() + except Exception: + nSelections = 0 + for i in range(nSelections): + rv.append(text.getSelection(i)) + + return rv + + def getChildAtOffset(self, obj, offset): + try: + hypertext = obj.queryHypertext() + except NotImplementedError: + tokens = ["SCRIPT UTILITIES:", obj, "does not implement the hypertext interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + except Exception: + tokens = ["SCRIPT UTILITIES: Exception querying hypertext interface for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + index = hypertext.getLinkIndex(offset) + if index == -1: + return None + + hyperlink = hypertext.getLink(index) + if not hyperlink: + tokens = ["SCRIPT UTILITIES: No hyperlink object at index", index, "for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + child = hyperlink.getObject(0) + tokens = ["SCRIPT UTILITIES: Hyperlink object at index", index, "for", obj, "is", child] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if offset != hyperlink.startIndex: + msg = ( + f"SCRIPT UTILITIES: Hyperlink start index {hyperlink.startIndex} " + f"should match the offset {offset}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + return child + + def findChildAtOffset(self, obj, offset): + """Attempts to correct for off-by-one brokenness in hypertext implementations. + + We're seeing off-by-one errors in (at least) Chromium where the text + at a given offset is an embedded object character, but retrieving the + child at that offset returns None. + + This method handles this condition by checking for the child at the + previous and next offsets. If there's a child, and its offset in parent + matches the desired offset, return that child. + """ + + if child := self.getChildAtOffset(obj, offset): + return child + + if child_before := self.getChildAtOffset(obj, offset - 1): + offset_in_parent = self.characterOffsetInParent(child_before) + if offset_in_parent == offset: + tokens = [f"SCRIPT UTILITIES: Corrected child at offset {offset} in", obj, "is", + child_before, f"at offset {offset - 1}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return child_before + + if child_after := self.getChildAtOffset(obj, offset + 1): + offset_in_parent = self.characterOffsetInParent(child_after) + if offset_in_parent == offset: + tokens = [f"SCRIPT UTILITIES: Corrected child at offset {offset} in", obj, "is", + child_after, f"at offset {offset + 1}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return child_after + + return None + + def characterOffsetInParent(self, obj): + """Returns the character offset of the embedded object + character for this object in its parent's accessible text. + + Arguments: + - obj: an Accessible that should implement the accessible + hyperlink specialization. + + Returns an integer representing the character offset of the + embedded object character for this hyperlink in its parent's + accessible text, or -1 something was amuck. + """ + + offset = -1 + try: + hyperlink = obj.queryHyperlink() + except NotImplementedError: + tokens = ["SCRIPT UTILITIES:", obj, "does not implement the hyperlink interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + # We need to make sure that this is an embedded object in + # some accessible text (as opposed to an imagemap link). + # + parent = AXObject.get_parent(obj) + try: + parent.queryText() + offset = hyperlink.startIndex + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting startIndex for", + obj, "in parent", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + tokens = ["SCRIPT UTILITIES: startIndex of", obj, f"is {offset}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return offset + + def clearTextSelection(self, obj): + """Clears the text selection if the object supports it. + + Arguments: + - obj: the Accessible object. + """ + + try: + text = obj.queryText() + except Exception: + return + + for i in range(text.getNSelections()): + text.removeSelection(i) + + def containsOnlyEOCs(self, obj): + try: + string = obj.queryText().getText(0, -1) + except Exception: + return False + + return string and not re.search(r"[^\ufffc]", string) + + def expandEOCs(self, obj, startOffset=0, endOffset=-1): + """Expands the current object replacing EMBEDDED_OBJECT_CHARACTERS + with their text. + + Arguments + - obj: the object whose text should be expanded + - startOffset: the offset of the first character to be included + - endOffset: the offset of the last character to be included + + Returns the fully expanded text for the object. + """ + + try: + string = self.substring(obj, startOffset, endOffset) + except Exception: + return "" + + if self.EMBEDDED_OBJECT_CHARACTER not in string: + return string + + blockRoles = [Atspi.Role.HEADING, + Atspi.Role.LIST, + Atspi.Role.LIST_ITEM, + Atspi.Role.PARAGRAPH, + Atspi.Role.SECTION, + Atspi.Role.TABLE, + Atspi.Role.TABLE_CELL, + Atspi.Role.TABLE_ROW] + + toBuild = list(string) + for i, char in enumerate(toBuild): + if char == self.EMBEDDED_OBJECT_CHARACTER: + child = self.findChildAtOffset(obj, i + startOffset) + result = self.expandEOCs(child) + if child and AXObject.get_role(child) in blockRoles: + result += " " + toBuild[i] = result + + return "".join(toBuild) + + def isWordMisspelled(self, obj, offset): + """Identifies if the current word is flagged as misspelled by the + application. Different applications and toolkits flag misspelled + words differently. Thus each script will likely need to implement + its own version of this method. + + Arguments: + - obj: An accessible which implements the accessible text interface. + - offset: Offset in the accessible's text for which to retrieve the + attributes. + + Returns True if the word is flagged as misspelled. + """ + + attributes, start, end = self.textAttributes(obj, offset, True) + if attributes.get("invalid") == "spelling": + return True + if attributes.get("text-spelling") == "misspelled": + return True + if attributes.get("underline") in ["error", "spelling"]: + return True + + return False + + def getError(self, obj): + return AXUtilities.is_invalid_entry(obj) + + def getErrorMessage(self, obj): + return "" + + def isErrorMessage(self, obj): + return False + + def getCharacterAtOffset(self, obj, offset=None): + text = self.queryNonEmptyText(obj) + if text: + if offset is None: + offset = text.caretOffset + return text.getText(offset, offset + 1) + + return "" + + def queryNonEmptyText(self, obj): + """Get the text interface associated with an object, if it is + non-empty. + + Arguments: + - obj: an accessible object + """ + + try: + text = obj.queryText() + charCount = text.characterCount + except NotImplementedError: + pass + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting character count of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + if charCount: + return text + + return None + + def deletedText(self, event): + return event.any_data + + def insertedText(self, event): + if event.any_data: + return event.any_data + + msg = "SCRIPT UTILITIES: Broken text insertion event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if AXUtilities.is_password_text(event.source): + text = self.queryNonEmptyText(event.source) + if text: + string = text.getText(0, -1) + if string: + tokens = ["HACK: Returning last char in '", string, "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return string[-1] + + msg = "FAIL: Unable to correct broken text insertion event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return "" + + def selectedText(self, obj): + """Get the text selection for the given object. + + Arguments: + - obj: the text object to extract the selected text from. + + Returns: the selected text contents plus the start and end + offsets within the text. + """ + + textContents = "" + startOffset = endOffset = 0 + try: + textObj = obj.queryText() + except Exception: + nSelections = 0 + else: + nSelections = textObj.getNSelections() + + for i in range(0, nSelections): + [startOffset, endOffset] = textObj.getSelection(i) + if startOffset == endOffset: + continue + selectedText = self.expandEOCs(obj, startOffset, endOffset) + if i > 0: + textContents += " " + textContents += selectedText + + return [textContents, startOffset, endOffset] + + def getCaretContext(self): + obj = cthulhu_state.locusOfFocus + try: + offset = obj.queryText().caretOffset + except NotImplementedError: + offset = 0 + except Exception: + offset = -1 + + return obj, offset + + def getFirstCaretPosition(self, obj): + return obj, 0 + + def setCaretPosition(self, obj, offset, documentFrame=None): + cthulhu.setLocusOfFocus(None, obj, False) + self.setCaretOffset(obj, offset) + + def setCaretOffset(self, obj, offset): + """Set the caret offset on a given accessible. Similar to + Accessible.setCaretOffset() + + Arguments: + - obj: Given accessible object. + - offset: Offset to hich to set the caret. + """ + try: + texti = obj.queryText() + except Exception: + return None + + texti.setCaretOffset(offset) + + def substring(self, obj, startOffset, endOffset): + """Returns the substring of the given object's text specialization. + + Arguments: + - obj: an accessible supporting the accessible text specialization + - startOffset: the starting character position + - endOffset: the ending character position. Note that an end offset + of -1 means the last character + """ + + try: + text = obj.queryText() + except Exception: + return "" + + return text.getText(startOffset, endOffset) + + def getAppNameForAttribute(self, attribName): + """Converts the given Atk attribute name into the application's + equivalent. This is necessary because an application or toolkit + (e.g. Gecko) might invent entirely new names for the same text + attributes. + + Arguments: + - attribName: The name of the text attribute + + Returns the application's equivalent name if found or attribName + otherwise. + """ + + for key, value in self._script.attributeNamesDict.items(): + if value == attribName: + return key + + return attribName + + def getAtkNameForAttribute(self, attribName): + """Converts the given attribute name into the Atk equivalent. This + is necessary because an application or toolkit (e.g. Gecko) might + invent entirely new names for the same attributes. + + Arguments: + - attribName: The name of the text attribute + + Returns the Atk equivalent name if found or attribName otherwise. + """ + + return self._script.attributeNamesDict.get(attribName, attribName) + + def getAllTextAttributesForObject(self, obj, startOffset=0, endOffset=-1): + """Returns a list of (start, end, attrsDict) tuples for obj.""" + try: + text = obj.queryText() + except Exception: + return [] + + if endOffset == -1: + endOffset = text.characterCount + + tokens = ["SCRIPT UTILITIES: Getting text attributes for", obj, + f"chars: {startOffset}-{endOffset}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + startTime = time.time() + + rv = [] + offset = startOffset + while offset < endOffset: + try: + attrList, start, end = text.getAttributeRun(offset) + tokens = [f"SCRIPT UTILITIES: At {offset}:", attrList, f"({start}, {end})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception as error: + msg = f"SCRIPT UTILITIES: Exception getting attributes at {offset}: {error}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return rv + + attrDict = dict([attr.split(':', 1) for attr in attrList]) + rv.append((max(start, offset), end, attrDict)) + offset = max(end, offset + 1) + + endTime = time.time() + msg = f"SCRIPT UTILITIES: {len(rv)} attribute ranges found in {endTime - startTime:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return rv + + def textAttributes(self, acc, offset=None, get_defaults=False): + """Get the text attributes run for a given offset in a given accessible + + Arguments: + - acc: An accessible. + - offset: Offset in the accessible's text for which to retrieve the + attributes. + - get_defaults: Get the default attributes as well as the unique ones. + Default is True + + Returns a dictionary of attributes, a start offset where the attributes + begin, and an end offset. Returns ({}, 0, 0) if the accessible does not + supprt the text attribute. + """ + + rv = {} + try: + text = acc.queryText() + except Exception: + return rv, 0, 0 + + if get_defaults: + stringAndDict = self.stringToKeysAndDict(text.getDefaultAttributes()) + rv.update(stringAndDict[1]) + + if offset is None: + offset = text.caretOffset + + attrString, start, end = text.getAttributes(offset) + stringAndDict = self.stringToKeysAndDict(attrString) + rv.update(stringAndDict[1]) + + start = min(start, offset) + end = max(end, offset + 1) + + return rv, start, end + + def localizeTextAttribute(self, key, value): + if key == "weight" and (value == "bold" or int(value) > 400): + return messages.BOLD + + if key.endswith("spelling") or value == "spelling": + return messages.MISSPELLED + + localizedKey = text_attribute_names.getTextAttributeName(key, self._script) + + if key == "family-name": + localizedValue = value.split(",")[0].strip().strip('"') + elif value and value.endswith("px"): + value = value.split("px")[0] + if locale.localeconv()["decimal_point"] in value: + localizedValue = messages.pixelCount(float(value)) + else: + localizedValue = messages.pixelCount(int(value)) + elif key.endswith("color"): + r, g, b = self.rgbFromString(value) + if settings.useColorNames: + localizedValue = colornames.rgbToName(r, g, b) + else: + localizedValue = "%i %i %i" % (r, g, b) + else: + localizedValue = text_attribute_names.getTextAttributeName(value, self._script) + + return f"{localizedKey}: {localizedValue}" + + def splitSubstringByLanguage(self, obj, start, end): + """Returns a list of (start, end, string, language, dialect) tuples.""" + + rv = [] + allSubstrings = self.getLanguageAndDialectFromTextAttributes(obj, start, end) + for startOffset, endOffset, language, dialect in allSubstrings: + if start >= endOffset: + continue + if end <= startOffset: + break + startOffset = max(start, startOffset) + endOffset = min(end, endOffset) + string = self.substring(obj, startOffset, endOffset) + rv.append([startOffset, endOffset, string, language, dialect]) + + return rv + + def getLanguageAndDialectForSubstring(self, obj, start, end): + """Returns a (language, dialect) tuple. If multiple languages apply to + the substring, language and dialect will be empty strings. Callers must + do any preprocessing to avoid that condition.""" + + allSubstrings = self.getLanguageAndDialectFromTextAttributes(obj, start, end) + for startOffset, endOffset, language, dialect in allSubstrings: + if startOffset <= start and endOffset >= end: + return language, dialect + + return "", "" + + def getLanguageAndDialectFromTextAttributes(self, obj, startOffset=0, endOffset=-1): + """Returns a list of (start, end, language, dialect) tuples for obj + based on what is exposed via text attributes.""" + + rv = [] + attributeSet = self.getAllTextAttributesForObject(obj, startOffset, endOffset) + lastLanguage = lastDialect = "" + for (start, end, attrs) in attributeSet: + language = attrs.get("language", "") + dialect = "" + if "-" in language: + language, dialect = language.split("-", 1) + if rv and lastLanguage == language and lastDialect == dialect: + rv[-1] = rv[-1][0], end, language, dialect + else: + rv.append((start, end, language, dialect)) + lastLanguage, lastDialect = language, dialect + + return rv + + def willEchoCharacter(self, event): + """Given a keyboard event containing an alphanumeric key, + determine if the script is likely to echo it as a character. + """ + + if not cthulhu_state.locusOfFocus or not settings.enableEchoByCharacter: + return False + + if len(event.event_string) != 1 \ + or event.modifiers & keybindings.CTHULHU_CTRL_MODIFIER_MASK: + return False + + if AXUtilities.is_password_text(cthulhu_state.locusOfFocus): + return False + + if AXUtilities.is_editable(cthulhu_state.locusOfFocus): + return True + + return False + + ######################################################################### + # # + # Miscellaneous Utilities # + # # + ######################################################################### + + def _addRepeatSegment(self, segment, line, respectPunctuation=True): + """Add in the latest line segment, adjusting for repeat characters + and punctuation. + + Arguments: + - segment: the segment of repeated characters. + - line: the current built-up line to characters to speak. + - respectPunctuation: if False, ignore punctuation level. + + Returns: the current built-up line plus the new segment, after + adjusting for repeat character counts and punctuation. + """ + + from . import punctuation_settings + + style = settings.verbalizePunctuationStyle + isPunctChar = True + try: + level, action = punctuation_settings.getPunctuationInfo(segment[0]) + except Exception: + isPunctChar = False + count = len(segment) + if (count >= settings.repeatCharacterLimit) \ + and (segment[0] not in self._script.whitespace): + if (not respectPunctuation) \ + or (isPunctChar and (style <= level)): + repeatChar = chnames.getCharacterName(segment[0]) + repeatSegment = messages.repeatedCharCount(repeatChar, count) + line = f"{line} {repeatSegment}" + else: + line += segment + else: + line += segment + + return line + + def shouldVerbalizeAllPunctuation(self, obj): + if not (self.isCode(obj) or self.isCodeDescendant(obj)): + return False + + # If the user has set their punctuation level to All, then the synthesizer will + # do the work for us. If the user has set their punctuation level to None, then + # they really don't want punctuation and we mustn't override that. + style = _settingsManager.getSetting("verbalizePunctuationStyle") + if style in [settings.PUNCTUATION_STYLE_ALL, settings.PUNCTUATION_STYLE_NONE]: + return False + + return True + + def verbalizeAllPunctuation(self, string): + result = string + for symbol in set(re.findall(self.PUNCTUATION, result)): + charName = f" {chnames.getCharacterName(symbol)} " + result = re.sub(r"\%s" % symbol, charName, result) + + return result + + def adjustForLinks(self, obj, line, startOffset): + """Adjust line to include the word "link" after any hypertext links. + + Arguments: + - obj: the accessible object that this line came from. + - line: the string to adjust for links. + - startOffset: the caret offset at the start of the line. + + Returns: a new line adjusted to add the speaking of "link" after + text which is also a link. + """ + + from . import punctuation_settings + + endOffset = startOffset + len(line) + try: + hyperText = obj.queryHypertext() + nLinks = hyperText.getNLinks() + except Exception: + nLinks = 0 + + adjustedLine = list(line) + for n in range(nLinks, 0, -1): + link = hyperText.getLink(n - 1) + if not link: + continue + + # We only care about links in the string, line: + # + if startOffset < link.endIndex <= endOffset: + index = link.endIndex - startOffset + elif startOffset <= link.startIndex < endOffset: + index = len(line) + if link.endIndex < endOffset: + index -= 1 + else: + continue + + linkString = " " + messages.LINK + + # If the link was not followed by a whitespace or punctuation + # character, then add in a space to make it more presentable. + # + nextChar = "" + if index < len(line): + nextChar = adjustedLine[index] + if not (nextChar in self._script.whitespace \ + or punctuation_settings.getPunctuationInfo(nextChar)): + linkString += " " + adjustedLine[index:index] = linkString + + return "".join(adjustedLine) + + @staticmethod + def _processMultiCaseString(string): + return re.sub(r'(?<=[a-z])(?=[A-Z])', ' ', string) + + @staticmethod + def _convertWordToDigits(word): + if not word.isnumeric(): + return word + + return ' '.join(list(word)) + + def adjustForPronunciation(self, line): + """Adjust the line to replace words in the pronunciation dictionary, + with what those words actually sound like. + + Arguments: + - line: the string to adjust for words in the pronunciation dictionary. + + Returns: a new line adjusted for words found in the pronunciation + dictionary. + """ + + if settings.speakMultiCaseStringsAsWords: + line = self._processMultiCaseString(line) + + if self.speakMathSymbolNames(): + line = mathsymbols.adjustForSpeech(line) + + if settings.speakNumbersAsDigits: + words = self.WORDS_RE.split(line) + line = ''.join(map(self._convertWordToDigits, words)) + + if len(line) == 1 and not self._script.inSayAll(): + charname = chnames.getCharacterName(line) + if charname != line: + return charname + + if not settings.usePronunciationDictionary: + return line + + newLine = "" + words = self.WORDS_RE.split(line) + newLine = ''.join(map(pronunciation_dict.getPronunciation, words)) + + if settings.speakMultiCaseStringsAsWords: + newLine = self._processMultiCaseString(newLine) + + return newLine + + def adjustForRepeats(self, line): + """Adjust line to include repeat character counts. As some people + will want this and others might not, there is a setting in + settings.py that determines whether this functionality is enabled. + + repeatCharacterLimit = + + If is 0, then there would be no repeat characters. + Otherwise would be the number of same characters (or more) + in a row that cause the repeat character count output. + If the value is set to 1, 2 or 3 then it's treated as if it was + zero. In other words, no repeat character count is given. + + Arguments: + - line: the string to adjust for repeat character counts. + + Returns: a new line adjusted for repeat character counts (if enabled). + """ + + if (len(line) < 4) or (settings.repeatCharacterLimit < 4): + return line + + newLine = '' + segment = lastChar = line[0] + + multipleChars = False + for i in range(1, len(line)): + if line[i] == lastChar: + segment += line[i] + else: + multipleChars = True + newLine = self._addRepeatSegment(segment, newLine) + segment = line[i] + + lastChar = line[i] + + return self._addRepeatSegment(segment, newLine, multipleChars) + + def adjustForDigits(self, string): + """Adjusts the string to convert digit-like text, such as subscript + and superscript numbers, into actual digits. + + Arguments: + - string: the string to be adjusted + + Returns: a new string which contains actual digits. + """ + + subscripted = set(re.findall(self.SUBSCRIPTS_RE, string)) + superscripted = set(re.findall(self.SUPERSCRIPTS_RE, string)) + + for number in superscripted: + new = [str(self.SUPERSCRIPT_DIGITS.index(d)) for d in number] + newString = messages.DIGITS_SUPERSCRIPT % "".join(new) + string = re.sub(number, newString, string) + + for number in subscripted: + new = [str(self.SUBSCRIPT_DIGITS.index(d)) for d in number] + newString = messages.DIGITS_SUBSCRIPT % "".join(new) + string = re.sub(number, newString, string) + + return string + + def indentationDescription(self, line): + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or not _settingsManager.getSetting('enableSpeechIndentation'): + return "" + + line = line.replace("\u00a0", " ") + end = re.search("[^ \t]", line) + if end: + line = line[:end.start()] + + result = "" + spaces = [m.span() for m in re.finditer(" +", line)] + tabs = [m.span() for m in re.finditer("\t+", line)] + spans = sorted(spaces + tabs) + for (start, end) in spans: + if (start, end) in spaces: + result += f"{messages.spacesCount(end - start)} " + else: + result += f"{messages.tabsCount(end - start)} " + + return result + + @staticmethod + def absoluteMouseCoordinates(): + """Gets the absolute position of the mouse pointer.""" + + from gi.repository import Gtk + rootWindow = Gtk.Window().get_screen().get_root_window() + window, x, y, modifiers = rootWindow.get_pointer() + + return x, y + + @staticmethod + def appendString(text, newText, delimiter=" "): + """Appends the newText to the given text with the delimiter in between + and returns the new string. Edge cases, such as no initial text or + no newText, are handled gracefully.""" + + if not newText: + return text + if not text: + return newText + + return text + delimiter + newText + + def treatAsDuplicateEvent(self, event1, event2): + if not (event1 and event2): + return False + + # The goal is to find event spam so we can ignore the event. + if event1 == event2: + return False + + return event1.source == event2.source \ + and event1.type == event2.type \ + and event1.detail1 == event2.detail1 \ + and event1.detail2 == event2.detail2 \ + and event1.any_data == event2.any_data + + def isAutoTextEvent(self, event): + """Returns True if event is associated with text being autocompleted + or autoinserted or autocorrected or autosomethingelsed. + + Arguments: + - event: the accessible event being examined + """ + + if event.type.startswith("object:text-changed:insert"): + if not event.any_data or not event.source: + return False + + if not AXUtilities.is_editable(event.source): + return False + if not AXUtilities.is_showing(event.source): + return False + if AXUtilities.is_focusable(event.source): + AXObject.clear_cache(event.source) + if not AXUtilities.is_focused(event.source): + return False + + lastKey, mods = self.lastKeyAndModifiers() + if lastKey == "Tab" and event.any_data != "\t": + return True + if lastKey == "Return" and event.any_data != "\n": + return True + if lastKey in ["Up", "Down", "Page_Up", "Page_Down"]: + return self.isEditableDescendantOfComboBox(event.source) + if not self.lastInputEventWasPrintableKey(): + return False + + string = event.source.queryText().getText(0, -1) + if string.endswith(event.any_data): + selection, start, end = self.selectedText(event.source) + if selection == event.any_data: + return True + if string == event.any_data and string.endswith(selection): + beginning = string[:string.find(selection)] + return beginning.lower().endswith(lastKey.lower()) + + return False + + def isSentenceDelimiter(self, currentChar, previousChar): + """Returns True if we are positioned at the end of a sentence. + This is determined by checking if the current character is a + white space character and the previous character is one of the + normal end-of-sentence punctuation characters. + + Arguments: + - currentChar: the current character + - previousChar: the previous character + + Returns True if the given character is a sentence delimiter. + """ + + if currentChar == '\r' or currentChar == '\n': + return True + + return currentChar in self._script.whitespace \ + and previousChar in '!.?:;' + + def isWordDelimiter(self, character): + """Returns True if the given character is a word delimiter. + + Arguments: + - character: the character in question + + Returns True if the given character is a word delimiter. + """ + + return character in self._script.whitespace \ + or character in r'!*+,-./:;<=>?@[\]^_{|}' \ + or character == self._script.NO_BREAK_SPACE_CHARACTER + + def intersectingRegion(self, obj1, obj2, coordType=None): + """Returns the extents of the intersection of obj1 and obj2.""" + + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + try: + extents1 = obj1.queryComponent().getExtents(coordType) + extents2 = obj2.queryComponent().getExtents(coordType) + except Exception: + return 0, 0, 0, 0 + + return self.intersection(extents1, extents2) + + def intersection(self, extents1, extents2): + x1, y1, width1, height1 = extents1 + x2, y2, width2, height2 = extents2 + + xPoints1 = range(x1, x1 + width1 + 1) + xPoints2 = range(x2, x2 + width2 + 1) + xIntersection = sorted(set(xPoints1).intersection(set(xPoints2))) + + yPoints1 = range(y1, y1 + height1 + 1) + yPoints2 = range(y2, y2 + height2 + 1) + yIntersection = sorted(set(yPoints1).intersection(set(yPoints2))) + + if not (xIntersection and yIntersection): + return 0, 0, 0, 0 + + x = xIntersection[0] + y = yIntersection[0] + width = xIntersection[-1] - x + height = yIntersection[-1] - y + + return x, y, width, height + + def containsRegion(self, extents1, extents2): + return self.intersection(extents1, extents2) != (0, 0, 0, 0) + + @staticmethod + def _allNamesForKeyCode(keycode): + keymap = Gdk.Keymap.get_default() + entries = keymap.get_entries_for_keycode(keycode)[-1] + return list(map(Gdk.keyval_name, set(entries))) + + @staticmethod + def _lastKeyCodeAndModifiers(): + if not isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + return 0, 0 + + event = cthulhu_state.lastNonModifierKeyEvent + if event: + return event.hw_code, event.modifiers + + return 0, 0 + + @staticmethod + def lastKeyAndModifiers(): + """Convenience method which returns a tuple containing the event + string and modifiers of the last non-modifier key event or ("", 0) + if there is no such event.""" + + if isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent) \ + and cthulhu_state.lastNonModifierKeyEvent: + event = cthulhu_state.lastNonModifierKeyEvent + if event.keyval_name in ["BackSpace", "Delete"]: + eventStr = event.keyval_name + else: + eventStr = event.event_string + mods = cthulhu_state.lastInputEvent.modifiers + else: + eventStr = "" + mods = 0 + + return (eventStr, mods) + + @staticmethod + def labelFromKeySequence(sequence): + """Turns a key sequence into a user-presentable label.""" + + try: + from gi.repository import Gtk + key, mods = Gtk.accelerator_parse(sequence) + newSequence = Gtk.accelerator_get_label(key, mods) + if newSequence and \ + (not newSequence.endswith('+') or newSequence.endswith('++')): + sequence = newSequence + except Exception: + if sequence.endswith(" "): + sequence += chnames.getCharacterName(" ") + sequence = sequence.replace("<", "") + sequence = sequence.replace(">", " ").strip() + + return keynames.localizeKeySequence(sequence) + + def mnemonicShortcutAccelerator(self, obj): + """Gets the mnemonic, accelerator string and possibly shortcut + for the given object. These are based upon the first accessible + action for the object. + + Arguments: + - obj: the Accessible object + + Returns: list containing strings: [mnemonic, shortcut, accelerator] + """ + + try: + return self._script.generatorCache[self.KEY_BINDING][obj] + except Exception: + if self.KEY_BINDING not in self._script.generatorCache: + self._script.generatorCache[self.KEY_BINDING] = {} + + keybinding = AXObject.get_action_key_binding(obj, 0) + if not keybinding: + self._script.generatorCache[self.KEY_BINDING][obj] = ["", "", ""] + return self._script.generatorCache[self.KEY_BINDING][obj] + + # Action is a string in the format, where the mnemonic and/or + # accelerator can be missing. + # + # ;; + # + # The keybindings in should be separated by ":" + # + + bindingStrings = keybinding.split(';') + if len(bindingStrings) == 3: + mnemonic = bindingStrings[0] + fullShortcut = bindingStrings[1] + accelerator = bindingStrings[2] + elif len(bindingStrings) > 0: + mnemonic = "" + fullShortcut = bindingStrings[0] + try: + accelerator = bindingStrings[1] + except Exception: + accelerator = "" + else: + mnemonic = "" + fullShortcut = "" + accelerator = "" + + fullShortcut = fullShortcut.replace(":", " ").strip() + fullShortcut = self.labelFromKeySequence(fullShortcut) + mnemonic = self.labelFromKeySequence(mnemonic) + accelerator = self.labelFromKeySequence(accelerator) + + if self.KEY_BINDING not in self._script.generatorCache: + self._script.generatorCache[self.KEY_BINDING] = {} + + self._script.generatorCache[self.KEY_BINDING][obj] = \ + [mnemonic, fullShortcut, accelerator] + return self._script.generatorCache[self.KEY_BINDING][obj] + + @staticmethod + def stringToKeysAndDict(string): + """Converts a string made up of a series of :; pairs + into a dictionary of keys and values. Text before the colon is the + key and text afterwards is the value. The final semi-colon, if + found, is ignored. + + Arguments: + - string: the string of tokens containing :; pairs. + + Returns a list containing two items: + A list of the keys in the order they were extracted from the + string and a dictionary of key/value items. + """ + + try: + items = [s.strip() for s in string.split(";")] + items = [item for item in items if len(item.split(':')) == 2] + keys = [item.split(':')[0].strip() for item in items] + dictionary = dict([item.split(':') for item in items]) + except Exception: + return [], {} + + return [keys, dictionary] + + def textForValue(self, obj): + """Returns the text to be displayed for the object's current value. + + Arguments: + - obj: the Accessible object that may or may not have a value. + + Returns a string representing the value. + """ + + attrs = self.objectAttributes(obj, False) + valuetext = attrs.get("valuetext") + if valuetext: + return valuetext + + try: + value = obj.queryValue() + except NotImplementedError: + return "" + else: + currentValue = value.currentValue + + # "The reports of my implementation are greatly exaggerated." + try: + maxValue = value.maximumValue + except Exception as error: + maxValue = 0.0 + tokens = ["SCRIPT UTILITIES: Could not get maximum value for", obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + try: + minValue = value.minimumValue + except Exception as error: + minValue = 0.0 + tokens = ["SCRIPT UTILITIES: Could not get minimum value for", obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + try: + minIncrement = value.minimumIncrement + except Exception as error: + minIncrement = (maxValue - minValue) / 100.0 + tokens = ["SCRIPT UTILITIES: Could not get minimum increment for", obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if minIncrement != 0.0: + try: + decimalPlaces = math.ceil(max(0, -math.log10(minIncrement))) + except ValueError as error: + tokens = ["SCRIPT UTILITIES: Could not calculate decimal places for", + obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + elif abs(currentValue) < 1: + decimalPlaces = 1 + else: + decimalPlaces = 0 + + formatter = "%%.%df" % decimalPlaces + return formatter % currentValue + + @staticmethod + def unicodeValueString(character): + """ Returns a four hex digit representation of the given character + + Arguments: + - The character to return representation + + Returns a string representaition of the given character unicode vlue + """ + + try: + return f"{ord(character):04x}" + except Exception: + debug.printException(debug.LEVEL_WARNING) + return "" + + def getLineContentsAtOffset(self, obj, offset, layoutMode=True, useCache=True): + return [] + + def getObjectContentsAtOffset(self, obj, offset=0, useCache=True): + return [] + + def previousContext(self, obj=None, offset=-1, skipSpace=False): + if not obj: + obj, offset = self.getCaretContext() + + return obj, offset - 1 + + def nextContext(self, obj=None, offset=-1, skipSpace=False): + if not obj: + obj, offset = self.getCaretContext() + + return obj, offset + 1 + + def lastContext(self, root): + offset = 0 + text = self.queryNonEmptyText(root) + if text: + offset = text.characterCount - 1 + + return root, offset + + def getHyperlinkRange(self, obj): + """Returns the text range in parent associated with obj.""" + + try: + hyperlink = obj.queryHyperlink() + start, end = hyperlink.startIndex, hyperlink.endIndex + except NotImplementedError: + tokens = ["SCRIPT UTILITIES:", obj, "does not implement the hyperlink interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1 + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting hyperlink indices for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1 + + return start, end + + def selectedChildren(self, obj): + children = AXSelection.get_selected_children(obj) + if children: + return children + + msg = "SCRIPT UTILITIES: Selected children not retrieved via selection interface." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + role = AXObject.get_role(obj) + if role == Atspi.Role.MENU and not children: + children = self.findAllDescendants(obj, AXUtilities.is_selected) + + if role == Atspi.Role.COMBO_BOX \ + and children and AXObject.get_role(children[0]) == Atspi.Role.MENU: + children = self.selectedChildren(children[0]) + name = AXObject.get_name(obj) + if not children and name: + def pred(x): + return AXObject.get_name(x) == name + + children = self.findAllDescendants(obj, pred) + + return children + + def speakSelectedCellRange(self, obj): + return False + + def getSelectionContainer(self, obj): + if not obj: + return None + + if AXObject.supports_selection(obj): + return obj + + rolemap = { + Atspi.Role.CANVAS: [Atspi.Role.LAYERED_PANE], + Atspi.Role.ICON: [Atspi.Role.LAYERED_PANE], + Atspi.Role.LIST_ITEM: [Atspi.Role.LIST_BOX], + Atspi.Role.TREE_ITEM: [Atspi.Role.TREE, Atspi.Role.TREE_TABLE], + Atspi.Role.TABLE_CELL: [Atspi.Role.TABLE, Atspi.Role.TREE_TABLE], + Atspi.Role.TABLE_ROW: [Atspi.Role.TABLE, Atspi.Role.TREE_TABLE], + } + + matchingRoles = rolemap.get(AXObject.get_role(obj)) + def isMatch(x): + if matchingRoles and AXObject.get_role(x) not in matchingRoles: + return False + return AXObject.supports_selection(x) + + return AXObject.find_ancestor(obj, isMatch) + + def selectableChildCount(self, obj): + if not AXObject.supports_selection(obj): + return 0 + + if AXObject.supports_table(obj): + rows, cols = self.rowAndColumnCount(obj) + return max(0, rows) + + rolemap = { + Atspi.Role.LIST_BOX: [Atspi.Role.LIST_ITEM], + Atspi.Role.TREE: [Atspi.Role.TREE_ITEM], + } + + role = AXObject.get_role(obj) + if role not in rolemap: + return AXObject.get_child_count(obj) + + def isMatch(x): + return AXObject.get_role(x) in rolemap.get(role) + + return len(self.findAllDescendants(obj, isMatch)) + + def selectedChildCount(self, obj): + if AXObject.supports_table(obj): + table = obj.queryTable() + if table.nSelectedRows: + return table.nSelectedRows + + return AXSelection.get_selected_child_count(obj) + + def popupMenuFor(self, obj): + if obj is None: + return None + + menus = [child for child in AXObject.iter_children(obj, AXUtilities.is_menu)] + for menu in menus: + if AXUtilities.is_enabled(menu): + return menu + + return None + + def isButtonWithPopup(self, obj): + return AXUtilities.is_button(obj) and AXUtilities.has_popup(obj) + + def isPopupMenuForCurrentItem(self, obj): + if obj == cthulhu_state.locusOfFocus: + return False + + if not AXUtilities.is_menu(obj): + return False + + name = AXObject.get_name(obj) + if not name: + return False + + return name == AXObject.get_name(cthulhu_state.locusOfFocus) + + def isMenuWithNoSelectedChild(self, obj): + return AXUtilities.is_menu(obj) and not self.selectedChildCount(obj) + + def isMenuButton(self, obj): + return AXUtilities.is_button(obj) and self.popupMenuFor(obj) is not None + + def inMenu(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + if obj is None: + return False + + if AXUtilities.is_menu_item_of_any_kind(obj) or AXUtilities.is_menu(obj): + return True + + if AXUtilities.is_panel(obj) or AXUtilities.is_separator(obj): + return AXObject.find_ancestor(obj, AXUtilities.is_menu) is not None + + return False + + def inContextMenu(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + if not self.inMenu(obj): + return False + + return AXObject.find_ancestor(obj, self.isContextMenu) is not None + + def _contextMenuParentRoles(self): + return Atspi.Role.FRAME, Atspi.Role.WINDOW + + def isContextMenu(self, obj): + if not AXUtilities.is_menu(obj): + return False + + return AXObject.get_role(AXObject.get_parent(obj)) in self._contextMenuParentRoles() + + def isTopLevelMenu(self, obj): + if not AXUtilities.is_menu(obj): + return False + return AXObject.get_parent(obj) == self.topLevelObject(obj) + + def isSingleLineAutocompleteEntry(self, obj): + if not AXUtilities.is_entry(obj): + return False + if not AXUtilities.supports_autocompletion(obj): + return False + return AXUtilities.is_single_line(obj) + + def isEntryCompletionPopupItem(self, obj): + return False + + def getEntryForEditableComboBox(self, obj): + if not AXUtilities.is_combo_box(obj): + return None + + children = [x for x in AXObject.iter_children(obj, self.isEditableTextArea)] + if len(children) == 1: + return children[0] + + return None + + def isEditableComboBox(self, obj): + return self.getEntryForEditableComboBox(obj) is not None + + def isEditableDescendantOfComboBox(self, obj): + if not AXUtilities.is_editable(obj): + return False + + return AXObject.find_ancestor(obj, AXUtilities.is_combo_box) is not None + + def getComboBoxValue(self, obj): + if not AXObject.get_child_count(obj): + return self.displayedText(obj) + + entry = self.getEntryForEditableComboBox(obj) + if entry: + return self.displayedText(entry) + + selected = self._script.utilities.selectedChildren(obj) + selected = selected or self._script.utilities.selectedChildren(AXObject.get_child(obj, 0)) + if len(selected) == 1: + return selected[0].name or self.displayedText(selected[0]) + + return self.displayedText(obj) + + def isPopOver(self, obj): + return False + + def isNonModalPopOver(self, obj): + if not self.isPopOver(obj): + return False + return not AXUtilities.is_modal(obj) + + def isUselessPanel(self, obj): + return False + + def rgbFromString(self, attributeValue): + regex = re.compile(r"rgb|[^\w,]", re.IGNORECASE) + string = re.sub(regex, "", attributeValue) + red, green, blue = string.split(",") + + return int(red), int(green), int(blue) + + def isClickableElement(self, obj): + return False + + def hasLongDesc(self, obj): + return False + + def hasDetails(self, obj): + return False + + def isDetails(self, obj): + return False + + def detailsFor(self, obj): + return [] + + def hasVisibleCaption(self, obj): + return False + + def popupType(self, obj): + return '' + + def headingLevel(self, obj): + if not AXUtilities.is_heading(obj): + return 0 + + attrs = self.objectAttributes(obj) + + try: + value = int(attrs.get('level', '0')) + except ValueError: + tokens = ["SCRIPT UTILITIES: Exception getting value for", obj, "(", attrs, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return 0 + + return value + + def hasMeaningfulToggleAction(self, obj): + return AXObject.has_action(obj, "toggle") \ + or AXObject.has_action(obj, object_properties.ACTION_TOGGLE) + + def containingTableHeader(self, obj): + if AXUtilities.is_table_header(obj): + return obj + + return AXObject.find_ancestor(obj, AXUtilities.is_table_header) + + def columnHeadersForCell(self, obj): + result = self._columnHeadersForCell(obj) + # There either are no headers, or we got all of them. + if len(result) != 1: + return result + + others = self._columnHeadersForCell(result[0]) + while len(others) == 1 and others[0] not in result: + result.insert(0, others[0]) + others = self._columnHeadersForCell(result[0]) + + return result + + def _columnHeadersForCell(self, obj): + if not obj: + msg = "SCRIPT UTILITIES: Attempted to get column headers for null cell" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return [] + + if AXObject.supports_table_cell(obj): + tableCell = obj.queryTableCell() + try: + headers = tableCell.columnHeaderCells + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting column headers for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + return headers + + parent = AXObject.find_ancestor(obj, AXObject.supports_table) + try: + table = parent.queryTable() + except Exception: + return [] + + row, col = self.coordinatesForCell(obj) + rowspan, colspan = self.rowAndColumnSpan(obj) + + headers = [] + for c in range(col, col+colspan): + headers.append(table.getColumnHeader(c)) + + return headers + + def rowHeadersForCell(self, obj): + result = self._rowHeadersForCell(obj) + # There either are no headers, or we got all of them. + if len(result) != 1: + return result + + others = self._rowHeadersForCell(result[0]) + while len(others) == 1 and others[0] not in result: + result.insert(0, others[0]) + others = self._rowHeadersForCell(result[0]) + + return result + + def _rowHeadersForCell(self, obj): + if not obj: + msg = "SCRIPT UTILITIES: Attempted to get row headers for null cell" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return [] + + if AXObject.supports_table_cell(obj): + tableCell = obj.queryTableCell() + try: + headers = tableCell.rowHeaderCells + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting row headers for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + return headers + + parent = AXObject.find_ancestor(obj, AXObject.supports_table) + try: + table = parent.queryTable() + except Exception: + return [] + + row, col = self.coordinatesForCell(obj) + rowspan, colspan = self.rowAndColumnSpan(obj) + + headers = [] + for r in range(row, row+rowspan): + headers.append(table.getRowHeader(r)) + + return headers + + def columnHeaderForCell(self, obj): + headers = self.columnHeadersForCell(obj) + if headers: + return headers[0] + + return None + + def rowHeaderForCell(self, obj): + headers = self.rowHeadersForCell(obj) + if headers: + return headers[0] + + return None + + def _shouldUseTableCellInterfaceForCoordinates(self): + return True + + def coordinatesForCell(self, obj, preferAttribute=True, findCellAncestor=False): + if not AXUtilities.is_table_cell_or_header(obj): + if not findCellAncestor: + return -1, -1 + + cell = AXObject.find_ancestor(obj, AXUtilities.is_table_cell_or_header) + return self.coordinatesForCell(cell, preferAttribute, False) + + if AXObject.supports_table_cell(obj) \ + and self._shouldUseTableCellInterfaceForCoordinates(): + tableCell = obj.queryTableCell() + try: + successful, row, col = tableCell.position + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting table cell position of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + if successful: + tokens = ["SCRIPT UTILITIES: position of", obj, f"is row: {row}, col: {col}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return row, col + tokens = ["SCRIPT UTILITIES: Failed to get position of", obj, "via table cell"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + parent = AXObject.find_ancestor(obj, AXObject.supports_table) + if not parent: + tokens = ["SCRIPT UTILITIES: Couldn't find table-implementing ancestor for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1 + + try: + table = parent.queryTable() + except Exception: + tokens = ["SCRIPT UTILITIES: Exception querying table interface", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1 + + index = self.cellIndex(obj) + try: + row = table.getRowAtIndex(index) + col = table.getColumnAtIndex(index) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting row and column at index from", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return -1, -1 + + return row, col + + def rowAndColumnSpan(self, obj): + if not AXUtilities.is_table_cell_or_header(obj): + return -1, -1 + + if AXObject.supports_table_cell(obj): + tableCell = obj.queryTableCell() + try: + rowSpan, colSpan = tableCell.rowSpan, tableCell.columnSpan + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting table row and col span of", + obj, "via table cell"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + return rowSpan, colSpan + + parent = AXObject.find_ancestor(obj, AXObject.supports_table) + try: + table = parent.queryTable() + except Exception: + return -1, -1 + + row, col = self.coordinatesForCell(obj) + if (row < 0 or col < 0): + return -1, -1 + + return table.getRowExtentAt(row, col), table.getColumnExtentAt(row, col) + + def setSizeUnknown(self, obj): + return AXUtilities.is_indeterminate(obj) + + def rowOrColumnCountUnknown(self, obj): + return AXUtilities.is_indeterminate(obj) + + def rowAndColumnCount(self, obj, preferAttribute=True): + try: + table = obj.queryTable() + except Exception: + return -1, -1 + + return table.nRows, table.nColumns + + def _objectBoundsMightBeBogus(self, obj): + return False + + def _objectMightBeBogus(self, obj): + return False + + def containsPoint(self, obj, x, y, coordType, margin=2): + if self._objectBoundsMightBeBogus(obj) \ + and self.textAtPoint(obj, x, y, coordType) == ("", 0, 0): + return False + + if self._objectMightBeBogus(obj): + return False + + try: + component = obj.queryComponent() + except Exception: + return False + + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + if component.contains(x, y, coordType): + return True + + x1, y1 = x + margin, y + margin + if component.contains(x1, y1, coordType): + tokens = ["SCRIPT UTILITIES: ", obj, f"contains ({x1},{y1}); not ({x},{y}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def _boundsIncludeChildren(self, obj): + if obj is None: + return False + + if self.hasNoSize(obj): + return False + + return not (AXUtilities.is_menu(obj) or AXUtilities.is_page_tab(obj)) + + def treatAsEntry(self, obj): + return False + + def _treatAsLeafNode(self, obj): + if obj is None or AXObject.is_dead(obj): + return False + + if not AXObject.get_child_count(obj): + return True + + if AXUtilities.is_autocomplete(obj) or AXUtilities.is_table_row(obj): + return False + + if AXUtilities.is_combo_box(obj): + return AXObject.find_descendant(obj, AXUtilities.is_entry) is None + + if AXUtilities.is_link(obj) and AXObject.get_name(obj): + return True + + if AXUtilities.is_expandable(obj): + return not AXUtilities.is_expanded(obj) + + if AXUtilities.is_button(obj): + return True + + return False + + def accessibleAtPoint(self, root, x, y, coordType=None): + if self.isHidden(root): + return None + + try: + component = root.queryComponent() + except Exception: + tokens = ["SCRIPT UTILITIES: Exception querying component of", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + result = component.getAccessibleAtPoint(x, y, coordType) + tokens = ["SCRIPT UTILITIES: ", result, "is descendant of", root, f"at ({x}, {y})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + def descendantAtPoint(self, root, x, y, coordType=None): + if not root: + return None + + if not self.isShowingAndVisible(root): + return None + + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + if self.containsPoint(root, x, y, coordType): + if self._treatAsLeafNode(root) or not self._boundsIncludeChildren(root): + return root + elif self._treatAsLeafNode(root) or self._boundsIncludeChildren(root): + return None + + if AXObject.supports_table(root): + child = self.accessibleAtPoint(root, x, y, coordType) + if child and child != root: + cell = self.descendantAtPoint(child, x, y, coordType) + if cell: + return cell + return child + + candidates_showing = [] + candidates = [] + for child in AXObject.iter_children(root): + obj = self.descendantAtPoint(child, x, y, coordType) + if obj: + return obj + if not self.containsPoint(child, x, y, coordType): + continue + if self.queryNonEmptyText(child): + string = child.queryText().getText(0, -1) + if re.search(r"[^\ufffc\s]", string): + candidates.append(child) + if AXUtilities.is_showing(child): + candidates_showing.append(child) + + if len(candidates_showing) == 1: + return candidates_showing[0] + if len(candidates) == 1: + # It should have had state "showing" actually + return candidates[0] + + return None + + def _adjustPointForObj(self, obj, x, y, coordType): + return x, y + + def isMultiParagraphObject(self, obj): + if not obj: + return False + + if not AXObject.supports_text(obj): + return False + + text = obj.queryText() + string = text.getText(0, -1) + chunks = list(filter(lambda x: x.strip(), string.split("\n\n"))) + return len(chunks) > 1 + + def getWordAtOffsetAdjustedForNavigation(self, obj, offset=None): + try: + text = obj.queryText() + if offset is None: + offset = text.caretOffset + except Exception: + return "", 0, 0 + + word, start, end = self.getWordAtOffset(obj, offset) + prevObj, prevOffset = self._script.pointOfReference.get( + "penultimateCursorPosition", (None, -1)) + if prevObj != obj: + return word, start, end + + # If we're in an ongoing series of native navigation-by-word commands, just present the + # newly-traversed string. + prevWord, prevStart, prevEnd = self.getWordAtOffset(prevObj, prevOffset) + if self._script.pointOfReference.get("lastTextUnitSpoken") == "word": + if self.lastInputEventWasPrevWordNav(): + start = offset + end = prevOffset + elif self.lastInputEventWasNextWordNav(): + start = prevOffset + end = offset + + word = text.getText(start, end) + debugString = word.replace("\n", "\\n") + msg = ( + f"SCRIPT UTILITIES: Adjusted word at offset {offset} for ongoing word nav is " + f"'{debugString}' ({start}-{end})" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return word, start, end + + # Otherwise, attempt some smarts so that the user winds up with the same presentation + # they would get were this an ongoing series of native navigation-by-word commands. + if self.lastInputEventWasPrevWordNav(): + # If we moved left via native nav, this should be the start of a native-navigation + # word boundary, regardless of what ATK/AT-SPI2 tells us. + start = offset + + # The ATK/AT-SPI2 word typically ends in a space; if the ending is neither a space, + # nor an alphanumeric character, then suspect that character is a navigation boundary + # where we would have landed before via the native previous word command. + if not (word[-1].isspace() or word[-1].isalnum()): + end -= 1 + + elif self.lastInputEventWasNextWordNav(): + # If we moved right via native nav, this should be the end of a native-navigation + # word boundary, regardless of what ATK/AT-SPI2 tells us. + end = offset + + # This suggests we just moved to the end of the previous word. + if word != prevWord and prevStart < offset <= prevEnd: + start = prevStart + + # If the character to the left of our present position is neither a space, nor + # an alphanumeric character, then suspect that character is a navigation boundary + # where we would have landed before via the native next word command. + lastChar = text.getText(offset - 1, offset) + if not (lastChar.isspace() or lastChar.isalnum()): + start = offset - 1 + + word = text.getText(start, end) + + # We only want to present the newline character when we cross a boundary moving from one + # word to another. If we're in the same word, strip it out. + if "\n" in word and word == prevWord: + if word.startswith("\n"): + start += 1 + elif word.endswith("\n"): + end -= 1 + word = text.getText(start, end) + + word = text.getText(start, end) + debugString = word.replace("\n", "\\n") + msg = ( + f"SCRIPT UTILITIES: Adjusted word at offset {offset} for new word nav is " + f"'{debugString}' ({start}-{end})" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return word, start, end + + def getWordAtOffset(self, obj, offset=None): + try: + text = obj.queryText() + if offset is None: + offset = text.caretOffset + except Exception: + return "", 0, 0 + + word, start, end = text.getTextAtOffset(offset, Atspi.TextBoundaryType.WORD_START) + debugString = word.replace("\n", "\\n") + msg = ( + f"SCRIPT UTILITIES: Word at offset {offset} is " + f"'{debugString}' ({start}-{end})" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return word, start, end + + def textAtPoint(self, obj, x, y, coordType=None, boundary=None): + text = self.queryNonEmptyText(obj) + if not text: + return "", 0, 0 + + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + if boundary is None: + boundary = Atspi.TextBoundaryType.LINE_START + + x, y = self._adjustPointForObj(obj, x, y, coordType) + offset = text.getOffsetAtPoint(x, y, coordType) + if not 0 <= offset < text.characterCount: + return "", 0, 0 + + string, start, end = text.getTextAtOffset(offset, boundary) + if not string: + return "", start, end + + if boundary == Atspi.TextBoundaryType.WORD_START and not string.strip(): + return "", 0, 0 + + extents = text.getRangeExtents(start, end, coordType) + if not self.containsRegion(extents, (x, y, 1, 1)) and string != "\n": + return "", 0, 0 + + if not string.endswith("\n") or string == "\n": + return string, start, end + + if boundary == Atspi.TextBoundaryType.CHAR: + return string, start, end + + char = self.textAtPoint(obj, x, y, coordType, Atspi.TextBoundaryType.CHAR) + if char[0] == "\n" and char[2] - char[1] == 1: + return char + + return string, start, end + + def visibleRows(self, obj, boundingbox): + try: + table = obj.queryTable() + nRows = table.nRows + except Exception: + return [] + + tokens = ["SCRIPT UTILITIES: ", obj, f"has {nRows} rows"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + x, y, width, height = boundingbox + cell = self.descendantAtPoint(obj, x, y + 1) + row, col = self.coordinatesForCell(cell) + startIndex = max(0, row) + tokens = ["SCRIPT UTILITIES: First cell:", cell, f"(row: {row}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # Just in case the row above is a static header row in a scrollable table. + try: + extents = cell.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except Exception: + nextIndex = startIndex + else: + cell = self.descendantAtPoint(obj, x, y + extents.height + 1) + row, col = self.coordinatesForCell(cell) + nextIndex = max(startIndex, row) + tokens = ["SCRIPT UTILITIES: Next cell:", cell, f"(row: {row}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + cell = self.descendantAtPoint(obj, x, y + height - 1) + row, col = self.coordinatesForCell(cell) + tokens = ["SCRIPT UTILITIES: Last cell:", cell, f"(row: {row}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if row == -1: + row = nRows + endIndex = row + + rows = list(range(nextIndex, endIndex)) + if startIndex not in rows: + rows.insert(0, startIndex) + + return rows + + def getVisibleTableCells(self, obj): + try: + table = obj.queryTable() + except Exception: + return [] + + try: + component = obj.queryComponent() + extents = component.getExtents(Atspi.CoordType.SCREEN) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting extents of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + rows = self.visibleRows(obj, extents) + if not rows: + return [] + + colStartIndex, colEndIndex = self._getTableRowRange(obj) + if colStartIndex == colEndIndex: + return [] + + cells = [] + for col in range(colStartIndex, colEndIndex): + colHeader = table.getColumnHeader(col) + if colHeader: + cells.append(colHeader) + for row in rows: + try: + cell = table.getAccessibleAt(row, col) + except Exception: + continue + if cell and self.isOnScreen(cell): + cells.append(cell) + + return cells + + def _getTableRowRange(self, obj): + rowCount, columnCount = self.rowAndColumnCount(obj) + startIndex, endIndex = 0, columnCount + if not self.isSpreadSheetCell(obj): + return startIndex, endIndex + + parent = self.getTable(obj) + try: + component = parent.queryComponent() + except Exception: + tokens = ["SCRIPT UTILITIES: Exception querying component interface of", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return startIndex, endIndex + + x, y, width, height = component.getExtents(Atspi.CoordType.SCREEN) + cell = component.getAccessibleAtPoint(x+1, y, Atspi.CoordType.SCREEN) + if cell: + row, column = self.coordinatesForCell(cell) + startIndex = column + + cell = component.getAccessibleAtPoint(x+width-1, y, Atspi.CoordType.SCREEN) + if cell: + row, column = self.coordinatesForCell(cell) + endIndex = column + 1 + + return startIndex, endIndex + + def getShowingCellsInSameRow(self, obj, forceFullRow=False): + parent = self.getTable(obj) + try: + table = parent.queryTable() + except Exception: + tokens = ["SCRIPT UTILITIES: Exception querying table interface of", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + row, column = self.coordinatesForCell(obj, False) + if row == -1: + return [] + + if forceFullRow: + startIndex, endIndex = 0, table.nColumns + else: + startIndex, endIndex = self._getTableRowRange(obj) + if startIndex == endIndex: + return [] + + cells = [] + for i in range(startIndex, endIndex): + cell = table.getAccessibleAt(row, i) + if AXUtilities.is_showing(cell): + cells.append(cell) + + return cells + + def cellForCoordinates(self, obj, row, column, showingOnly=False): + try: + table = obj.queryTable() + except Exception: + return None + + cell = table.getAccessibleAt(row, column) + if not showingOnly: + return cell + + if AXUtilities.is_showing(cell): + return cell + + return None + + def isLastCell(self, obj): + if not AXUtilities.is_table_cell(obj): + return False + + parent = AXObject.find_ancestor(obj, AXObject.supports_table) + try: + table = parent.queryTable() + except Exception: + return False + + row, col = self.coordinatesForCell(obj) + return row + 1 == table.nRows and col + 1 == table.nColumns + + def isNonUniformTable(self, obj, maxRows=25, maxCols=25): + try: + table = obj.queryTable() + except Exception: + return False + + for r in range(min(maxRows, table.nRows)): + for c in range(min(maxCols, table.nColumns)): + if table.getRowExtentAt(r, c) > 1 \ + or table.getColumnExtentAt(r, c) > 1: + return True + + return False + + def isShowingAndVisible(self, obj): + if AXUtilities.is_showing(obj) and AXUtilities.is_visible(obj): + return True + + # TODO - JD: This really should be in the toolkit scripts. But it + # seems to be present in multiple toolkits, so it's either being + # inherited (e.g. from Gtk in Firefox Chrome, LO, Eclipse) or it + # may be an AT-SPI2 bug. For now, handling it here. + menuRoles = [Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.SEPARATOR] + if AXObject.get_role(obj) in menuRoles and self.isInOpenMenuBarMenu(obj): + tokens = ["HACK: Treating", obj, "as showing and visible"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def isZombie(self, obj): + index = AXObject.get_index_in_parent(obj) + topLevelRoles = [Atspi.Role.APPLICATION, + Atspi.Role.ALERT, + Atspi.Role.DIALOG, + Atspi.Role.LABEL, # For Unity Panel Service bug + Atspi.Role.PAGE, # For Evince bug + Atspi.Role.WINDOW, + Atspi.Role.FRAME] + role = AXObject.get_role(obj) + tokens = ["SCRIPT UTILITIES: ", obj, "is zombie:"] + if index == -1 and role not in topLevelRoles: + tokens.append("index is -1") + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + if AXUtilities.is_defunct(obj): + tokens.append("is defunct") + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + if AXUtilities.is_invalid_state(obj): + tokens.append("has invalid state") + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + if AXUtilities.is_invalid_role(obj): + tokens.append("has invalid role") + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def findReplicant(self, root, obj): + tokens = ["SCRIPT UTILITIES: Searching for replicant for", obj, "in", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not (root and obj): + return None + + if AXUtilities.is_table(root) or AXUtilities.is_embedded(root): + return None + + def isSame(x): + return self.isSameObject(x, obj, comparePaths=True, ignoreNames=True) + + if isSame(root): + replicant = root + else: + replicant = AXObject.find_descendant(root, isSame) + + tokens = ["HACK: Returning", replicant, "as replicant for Zombie", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return replicant + + def getFunctionalChildCount(self, obj): + relation = AXObject.get_relation(obj, Atspi.RelationType.NODE_PARENT_OF) + if relation: + return relation.get_n_targets() + return AXObject.get_child_count(obj) + + def getFunctionalChildren(self, obj, sibling=None): + result = AXObject.get_relation_targets(obj, Atspi.RelationType.NODE_PARENT_OF) + if result: + return result + if self.isDescriptionListTerm(sibling): + return self.descriptionListTerms(obj) + if self.isDescriptionListDescription(sibling): + return self.valuesForTerm(self.termForValue(sibling)) + return [x for x in AXObject.iter_children(obj)] + + def getFunctionalParent(self, obj): + relation = AXObject.get_relation(obj, Atspi.RelationType.NODE_CHILD_OF) + if relation: + return relation.get_target(0) + return AXObject.get_parent(obj) + + def getPositionAndSetSize(self, obj, **args): + if obj is None: + return -1, -1 + + if AXUtilities.is_table_cell(obj) and args.get("readingRow"): + row, col = self.coordinatesForCell(obj) + rowcount, colcount = self.rowAndColumnCount(self.getTable(obj)) + return row, rowcount + + if AXUtilities.is_combo_box(obj): + selected = self.selectedChildren(obj) + if selected: + obj = selected[0] + else: + def isMenu(x): + return AXUtilities.is_menu(x) or AXUtilities.is_list_box(x) + + selected = self.selectedChildren(AXObject.find_descendant(obj, isMenu)) + if selected: + obj = selected[0] + else: + return -1, -1 + + parent = self.getFunctionalParent(obj) + childCount = self.getFunctionalChildCount(parent) + if childCount > 100 and parent == AXObject.get_parent(obj): + return AXObject.get_index_in_parent(obj), childCount + + siblings = self.getFunctionalChildren(parent, obj) + if len(siblings) < 100 and not AXObject.find_ancestor(obj, AXUtilities.is_combo_box): + layoutRoles = [Atspi.Role.SEPARATOR, Atspi.Role.TEAROFF_MENU_ITEM] + + def isNotLayoutOnly(x): + return not (self.isZombie(x) or AXObject.get_role(x) in layoutRoles) + + siblings = list(filter(isNotLayoutOnly, siblings)) + + if not (siblings and obj in siblings): + return -1, -1 + + if self.isFocusableLabel(obj): + siblings = list(filter(self.isFocusableLabel, siblings)) + if len(siblings) == 1: + return -1, -1 + + position = siblings.index(obj) + setSize = len(siblings) + return position, setSize + + def termForValue(self, obj): + if not self.isDescriptionListDescription(obj): + return None + + while obj and not self.isDescriptionListTerm(obj): + obj = AXObject.get_previous_sibling(obj) + + return obj + + def valuesForTerm(self, obj): + if not self.isDescriptionListTerm(obj): + return [] + + values = [] + obj = AXObject.get_next_sibling(obj) + while obj and self.isDescriptionListDescription(obj): + values.append(obj) + obj = AXObject.get_next_sibling(obj) + + return values + + def getValueCountForTerm(self, obj): + return len(self.valuesForTerm(obj)) + + def getRoleDescription(self, obj, isBraille=False): + return "" + + def getCachedTextSelection(self, obj): + textSelections = self._script.pointOfReference.get('textSelections', {}) + start, end, string = textSelections.get(hash(obj), (0, 0, '')) + tokens = ["SCRIPT UTILITIES: Cached selection for", obj, f"is '{string}' ({start}, {end})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return start, end, string + + def updateCachedTextSelection(self, obj): + try: + text = obj.queryText() + except NotImplementedError: + tokens = ["SCRIPT UTILITIES:", obj, "doesn't implement AtspiText"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + text = None + except Exception: + tokens = ["SCRIPT UTILITIES: Exception querying text interface for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + text = None + + if self._script.pointOfReference.get('entireDocumentSelected'): + selectedText, selectedStart, selectedEnd = self.allSelectedText(obj) + if not selectedText: + self._script.pointOfReference['entireDocumentSelected'] = False + self._script.pointOfReference['textSelections'] = {} + + textSelections = self._script.pointOfReference.get('textSelections', {}) + + # Because some apps and toolkits create, destroy, and duplicate objects + # and events. + if hash(obj) in textSelections: + value = textSelections.pop(hash(obj)) + for x in [k for k in textSelections.keys() if textSelections.get(k) == value]: + textSelections.pop(x) + + # TODO: JD - this doesn't yet handle the case of multiple non-contiguous + # selections in a single accessible object. + start, end, string = 0, 0, '' + if text: + try: + start, end = text.getSelection(0) + except Exception: + tokens = ["SCRIPT UTILITIES: Exception getting selected text for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + start = end = 0 + if start != end: + string = text.getText(start, end) + + tokens = ["SCRIPT UTILITIES: New selection for", obj, f"is '{string}' ({start}, {end})"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + textSelections[hash(obj)] = start, end, string + self._script.pointOfReference['textSelections'] = textSelections + + @staticmethod + def onClipboardContentsChanged(*args): + script = cthulhu_state.activeScript + if not script: + return + + if time.time() - Utilities._last_clipboard_update < 0.05: + msg = "SCRIPT UTILITIES: Clipboard contents change believed to be duplicate" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + Utilities._last_clipboard_update = time.time() + script.onClipboardContentsChanged(*args) + + def connectToClipboard(self): + if self._clipboardHandlerId is not None: + return + + clipboard = Gtk.Clipboard.get(Gdk.Atom.intern("CLIPBOARD", False)) + self._clipboardHandlerId = clipboard.connect( + 'owner-change', self.onClipboardContentsChanged) + + def disconnectFromClipboard(self): + if self._clipboardHandlerId is None: + return + + clipboard = Gtk.Clipboard.get(Gdk.Atom.intern("CLIPBOARD", False)) + clipboard.disconnect(self._clipboardHandlerId) + + def getClipboardContents(self): + clipboard = Gtk.Clipboard.get(Gdk.Atom.intern("CLIPBOARD", False)) + return clipboard.wait_for_text() + + def setClipboardText(self, text): + clipboard = Gtk.Clipboard.get(Gdk.Atom.intern("CLIPBOARD", False)) + clipboard.set_text(text, -1) + + def appendTextToClipboard(self, text): + clipboard = Gtk.Clipboard.get(Gdk.Atom.intern("CLIPBOARD", False)) + clipboard.request_text(self._appendTextToClipboardCallback, text) + + def _appendTextToClipboardCallback(self, clipboard, text, newText, separator="\n"): + text = text.rstrip("\n") + text = f"{text}{separator}{newText}" + clipboard.set_text(text, -1) + + def lastInputEventCameFromThisApp(self): + if not isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + return False + + event = cthulhu_state.lastNonModifierKeyEvent + return event and event.isFromApplication(self._script.app) + + def lastInputEventWasPrintableKey(self): + event = cthulhu_state.lastInputEvent + if not isinstance(event, input_event.KeyboardEvent): + return False + + return event.isPrintableKey() + + def lastInputEventWasCommand(self): + keyString, mods = self.lastKeyAndModifiers() + return mods & keybindings.CTRL_MODIFIER_MASK + + def lastInputEventWasPageSwitch(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString.isnumeric(): + return mods & keybindings.ALT_MODIFIER_MASK + + if keyString in ["Page_Up", "Page_Down"]: + return mods & keybindings.CTRL_MODIFIER_MASK + + return False + + def lastInputEventWasUnmodifiedArrow(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Left", "Right", "Up", "Down"]: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK \ + or mods & keybindings.SHIFT_MODIFIER_MASK \ + or mods & keybindings.ALT_MODIFIER_MASK \ + or mods & keybindings.CTHULHU_MODIFIER_MASK: + return False + + return True + + def lastInputEventWasCaretNav(self): + return self.lastInputEventWasCharNav() \ + or self.lastInputEventWasWordNav() \ + or self.lastInputEventWasLineNav() \ + or self.lastInputEventWasLineBoundaryNav() + + def lastInputEventWasCharNav(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Left", "Right"]: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK \ + or mods & keybindings.ALT_MODIFIER_MASK: + return False + + return True + + def lastInputEventWasWordNav(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Left", "Right"]: + return False + + return mods & keybindings.CTRL_MODIFIER_MASK + + def lastInputEventWasPrevWordNav(self): + keyString, mods = self.lastKeyAndModifiers() + if not keyString == "Left": + return False + + return mods & keybindings.CTRL_MODIFIER_MASK + + def lastInputEventWasNextWordNav(self): + keyString, mods = self.lastKeyAndModifiers() + if not keyString == "Right": + return False + + return mods & keybindings.CTRL_MODIFIER_MASK + + def lastInputEventWasLineNav(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Up", "Down"]: + return False + + if self.isEditableDescendantOfComboBox(cthulhu_state.locusOfFocus): + return False + + return not (mods & keybindings.CTRL_MODIFIER_MASK) + + def lastInputEventWasLineBoundaryNav(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Home", "End"]: + return False + + return not (mods & keybindings.CTRL_MODIFIER_MASK) + + def lastInputEventWasPageNav(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Page_Up", "Page_Down"]: + return False + + if self.isEditableDescendantOfComboBox(cthulhu_state.locusOfFocus): + return False + + return not (mods & keybindings.CTRL_MODIFIER_MASK) + + def lastInputEventWasFileBoundaryNav(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Home", "End"]: + return False + + return mods & keybindings.CTRL_MODIFIER_MASK + + def lastInputEventWasCaretNavWithSelection(self): + keyString, mods = self.lastKeyAndModifiers() + if mods & keybindings.SHIFT_MODIFIER_MASK: + return keyString in ["Home", "End", "Up", "Down", "Left", "Right"] + + return False + + def lastInputEventWasUndo(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'z' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return not (mods & keybindings.SHIFT_MODIFIER_MASK) + + return False + + def lastInputEventWasRedo(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'z' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return mods & keybindings.SHIFT_MODIFIER_MASK + + return False + + def lastInputEventWasCut(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'x' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return not (mods & keybindings.SHIFT_MODIFIER_MASK) + + return False + + def lastInputEventWasCopy(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'c' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return not (mods & keybindings.SHIFT_MODIFIER_MASK) + + return False + + def lastInputEventWasPaste(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'v' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return not (mods & keybindings.SHIFT_MODIFIER_MASK) + + return False + + def lastInputEventWasSelectAll(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'a' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return not (mods & keybindings.SHIFT_MODIFIER_MASK) + + return False + + def lastInputEventWasDelete(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString in ["Delete", "KP_Delete"]: + return True + + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'd' not in keynames: + return False + + return mods & keybindings.CTRL_MODIFIER_MASK + + def lastInputEventWasTab(self): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Tab", "ISO_Left_Tab"]: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK \ + or mods & keybindings.ALT_MODIFIER_MASK \ + or mods & keybindings.CTHULHU_MODIFIER_MASK: + return False + + return True + + def lastInputEventWasMouseButton(self): + return isinstance(cthulhu_state.lastInputEvent, input_event.MouseButtonEvent) + + def lastInputEventWasPrimaryMouseClick(self): + event = cthulhu_state.lastInputEvent + if isinstance(event, input_event.MouseButtonEvent): + return event.button == "1" and event.pressed + + return False + + def lastInputEventWasMiddleMouseClick(self): + event = cthulhu_state.lastInputEvent + if isinstance(event, input_event.MouseButtonEvent): + return event.button == "2" and event.pressed + + return False + + def lastInputEventWasSecondaryMouseClick(self): + event = cthulhu_state.lastInputEvent + if isinstance(event, input_event.MouseButtonEvent): + return event.button == "3" and event.pressed + + return False + + def lastInputEventWasPrimaryMouseRelease(self): + event = cthulhu_state.lastInputEvent + if isinstance(event, input_event.MouseButtonEvent): + return event.button == "1" and not event.pressed + + return False + + def lastInputEventWasMiddleMouseRelease(self): + event = cthulhu_state.lastInputEvent + if isinstance(event, input_event.MouseButtonEvent): + return event.button == "2" and not event.pressed + + return False + + def lastInputEventWasSecondaryMouseRelease(self): + event = cthulhu_state.lastInputEvent + if isinstance(event, input_event.MouseButtonEvent): + return event.button == "3" and not event.pressed + + return False + + def lastInputEventWasTableSort(self, delta=0.5): + event = cthulhu_state.lastInputEvent + if not event: + return False + + now = time.time() + if now - event.time > delta: + return False + + lastSortTime = self._script.pointOfReference.get('last-table-sort-time', 0.0) + if now - lastSortTime < delta: + return False + + if isinstance(event, input_event.MouseButtonEvent): + if not self.lastInputEventWasPrimaryMouseRelease(): + return False + elif isinstance(event, input_event.KeyboardEvent): + if not event.isHandledBy(self._script.leftClickReviewItem): + keyString, mods = self.lastKeyAndModifiers() + if keyString not in ["Return", "space", " "]: + return False + + return AXUtilities.is_table_header(cthulhu_state.locusOfFocus) + + def isPresentableExpandedChangedEvent(self, event): + if self.isSameObject(event.source, cthulhu_state.locusOfFocus): + return True + + if AXUtilities.is_table_row(event.source) or AXUtilities.is_list_box(event.source): + return True + + if AXUtilities.is_combo_box(event.source) or AXUtilities.is_button(event.source): + return AXUtilities.is_focused(event.source) + + return False + + def isPresentableTextChangedEventForLocusOfFocus(self, event): + if not event.type.startswith("object:text-changed:") \ + and not event.type.startswith("object:text-attributes-changed"): + return False + + if AXUtilities.is_menu_related(event.source) \ + or AXUtilities.is_slider(event.source) \ + or AXUtilities.is_spin_button(event.source) \ + or AXUtilities.is_label(event.source): + msg = "SCRIPT UTILITIES: Event is not being presented due to role" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if AXUtilities.is_focused(event.source): + if self.isTypeahead(event.source): + return True + if AXUtilities.is_password_text(event.source): + return True + if AXObject.is_dead(cthulhu_state.locusOfFocus): + return True + elif AXUtilities.is_table_cell(event.source) and not AXUtilities.is_selected(event.source): + msg = "SCRIPT UTILITIES: Event is not being presented due to role and states" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if cthulhu_state.locusOfFocus in [event.source, AXObject.get_parent(event.source)]: + return True + + msg = "SCRIPT UTILITIES: Event is not being presented due to lack of cause" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def isBackSpaceCommandTextDeletionEvent(self, event): + if not event.type.startswith("object:text-changed:delete"): + return False + + if self.isHidden(event.source): + return False + + keyString, mods = self.lastKeyAndModifiers() + if keyString == "BackSpace": + return True + + return False + + def isDeleteCommandTextDeletionEvent(self, event): + if not event.type.startswith("object:text-changed:delete"): + return False + + return self.lastInputEventWasDelete() + + def isUndoCommandTextDeletionEvent(self, event): + if not event.type.startswith("object:text-changed:delete"): + return False + + if not self.lastInputEventWasUndo(): + return False + + start, end, string = self.getCachedTextSelection(event.source) + return not string + + def isSelectedTextDeletionEvent(self, event): + if not event.type.startswith("object:text-changed:delete"): + return False + + if self.lastInputEventWasPaste(): + return False + + start, end, string = self.getCachedTextSelection(event.source) + return string and string.strip() == event.any_data.strip() + + def isSelectedTextInsertionEvent(self, event): + if not event.type.startswith("object:text-changed:insert"): + return False + + self.updateCachedTextSelection(event.source) + start, end, string = self.getCachedTextSelection(event.source) + return string and string == event.any_data and start == event.detail1 + + def isSelectedTextRestoredEvent(self, event): + if not self.lastInputEventWasUndo(): + return False + + if self.isSelectedTextInsertionEvent(event): + return True + + return False + + def isMiddleMouseButtonTextInsertionEvent(self, event): + if not event.type.startswith("object:text-changed:insert"): + return False + + return self.lastInputEventWasMiddleMouseClick() + + def isEchoableTextInsertionEvent(self, event): + if not event.type.startswith("object:text-changed:insert"): + return False + + if AXUtilities.is_focusable(event.source) \ + and not AXUtilities.is_focused(event.source) \ + and event.source != cthulhu_state.locusOfFocus: + msg = "SCRIPT UTILITIES: Not echoable text insertion event: " \ + "focusable source is not focused" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if AXUtilities.is_password_text(event.source): + return _settingsManager.getSetting("enableKeyEcho") + + if len(event.any_data.strip()) == 1: + return _settingsManager.getSetting("enableEchoByCharacter") + + return False + + def isEditableTextArea(self, obj): + if not self.isTextArea(obj): + return False + return AXUtilities.is_editable(obj) + + def isClipboardTextChangedEvent(self, event): + if not event.type.startswith("object:text-changed"): + return False + + if not self.lastInputEventWasCommand() or self.lastInputEventWasUndo(): + return False + + if self.isBackSpaceCommandTextDeletionEvent(event): + return False + + if "delete" in event.type and self.lastInputEventWasPaste(): + return False + + if not self.isEditableTextArea(event.source): + return False + + contents = self.getClipboardContents() + if not contents: + return False + if event.any_data == contents: + return True + if bool(re.search(r"\w", event.any_data)) != bool(re.search(r"\w", contents)): + return False + + # HACK: If the application treats each paragraph as a separate object, + # we'll get individual events for each paragraph rather than a single + # event whose any_data matches the clipboard contents. + if "\n" in contents and event.any_data.rstrip() in contents: + return True + + return False + + def objectContentsAreInClipboard(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + if not obj or AXObject.is_dead(obj): + return False + + contents = self.getClipboardContents() + if not contents: + return False + + string, start, end = self.selectedText(obj) + if string and string in contents: + return True + + obj = self.realActiveDescendant(obj) or obj + if AXObject.is_dead(obj): + return False + + return obj and AXObject.get_name(obj) in contents + + def clearCachedCommandState(self): + self._script.pointOfReference['undo'] = False + self._script.pointOfReference['redo'] = False + self._script.pointOfReference['paste'] = False + self._script.pointOfReference['last-selection-message'] = '' + + def handleUndoTextEvent(self, event): + if self.lastInputEventWasUndo(): + if not self._script.pointOfReference.get('undo'): + self._script.presentMessage(messages.UNDO) + self._script.pointOfReference['undo'] = True + self.updateCachedTextSelection(event.source) + return True + + if self.lastInputEventWasRedo(): + if not self._script.pointOfReference.get('redo'): + self._script.presentMessage(messages.REDO) + self._script.pointOfReference['redo'] = True + self.updateCachedTextSelection(event.source) + return True + + return False + + def handleUndoLocusOfFocusChange(self): + if self._locusOfFocusIsTopLevelObject(): + return False + + if self.lastInputEventWasUndo(): + if not self._script.pointOfReference.get('undo'): + self._script.presentMessage(messages.UNDO) + self._script.pointOfReference['undo'] = True + return True + + if self.lastInputEventWasRedo(): + if not self._script.pointOfReference.get('redo'): + self._script.presentMessage(messages.REDO) + self._script.pointOfReference['redo'] = True + return True + + return False + + def handlePasteLocusOfFocusChange(self): + if self._locusOfFocusIsTopLevelObject(): + return False + + if self.lastInputEventWasPaste(): + if not self._script.pointOfReference.get('paste'): + self._script.presentMessage( + messages.CLIPBOARD_PASTED_FULL, messages.CLIPBOARD_PASTED_BRIEF) + self._script.pointOfReference['paste'] = True + return True + + return False + + def eventIsUserTriggered(self, event): + if not cthulhu_state.lastInputEvent: + msg = "SCRIPT UTILITIES: Not user triggered: No last input event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + delta = time.time() - cthulhu_state.lastInputEvent.time + if delta > 1: + msg = f"SCRIPT UTILITIES: Not user triggered: Last input event {delta:.2f}s ago." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.isKeyGrabEvent(event): + msg = "INFO: Last key was consumed. Probably a bogus event from a key grab" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + return True + + def isKeyGrabEvent(self, event): + """ Returns True if this event appears to be a side-effect of an + X11 key grab. """ + if not isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + return False + return cthulhu_state.lastInputEvent.didConsume() and not cthulhu_state.openingDialog + + def presentFocusChangeReason(self): + if self.handleUndoLocusOfFocusChange(): + return True + if self.handlePasteLocusOfFocusChange(): + return True + return False + + def allItemsSelected(self, obj): + if not AXObject.supports_selection(obj): + return False + + if AXUtilities.is_expandable(obj) and not AXUtilities.is_expanded(obj): + return False + + if AXUtilities.is_combo_box(obj) or AXUtilities.is_menu(obj): + return False + + childCount = AXObject.get_child_count(obj) + if childCount == AXSelection.get_selected_child_count(obj): + # The selection interface gives us access to what is selected, which might + # not actually be a direct child. + child = AXSelection.get_selected_child(obj, 0) + if AXObject.get_parent(child) != obj: + return False + + msg = f"SCRIPT UTILITIES: All {childCount} children believed to be selected" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not AXObject.supports_table(obj): + return False + + table = obj.queryTable() + if table.nSelectedRows == table.nRows: + msg = f"SCRIPT UTILITIES: All {table.nRows} rows believed to be selected" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if table.nSelectedColumns == table.nColumns: + msg = f"SCRIPT UTILITIES: All {table.nColumns} columns believed to be selected" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def handleContainerSelectionChange(self, obj): + allAlreadySelected = self._script.pointOfReference.get('allItemsSelected') + allCurrentlySelected = self.allItemsSelected(obj) + if allAlreadySelected and allCurrentlySelected: + return True + + self._script.pointOfReference['allItemsSelected'] = allCurrentlySelected + if self.lastInputEventWasSelectAll() and allCurrentlySelected: + self._script.presentMessage(messages.CONTAINER_SELECTED_ALL) + cthulhu.setLocusOfFocus(None, obj, False) + return True + + return False + + def handleTextSelectionChange(self, obj, speakMessage=True): + # Note: This guesswork to figure out what actually changed with respect + # to text selection will get eliminated once the new text-selection API + # is added to ATK and implemented by the toolkits. (BGO 638378) + + if not AXObject.supports_text(obj): + return False + + oldStart, oldEnd, oldString = self.getCachedTextSelection(obj) + self.updateCachedTextSelection(obj) + newStart, newEnd, newString = self.getCachedTextSelection(obj) + + if self._speakTextSelectionState(len(newString)): + return True + + # Even though we present a message, treat it as unhandled so the new location is + # still presented. + if not self.lastInputEventWasCaretNavWithSelection() and oldString and not newString: + self._script.speakMessage(messages.SELECTION_REMOVED) + return False + + changes = [] + oldChars = set(range(oldStart, oldEnd)) + newChars = set(range(newStart, newEnd)) + if not oldChars.union(newChars): + return False + + if oldChars and newChars and not oldChars.intersection(newChars): + # A simultaneous unselection and selection centered at one offset. + changes.append([oldStart, oldEnd, messages.TEXT_UNSELECTED]) + changes.append([newStart, newEnd, messages.TEXT_SELECTED]) + else: + change = sorted(oldChars.symmetric_difference(newChars)) + if not change: + return False + + changeStart, changeEnd = change[0], change[-1] + 1 + if oldChars < newChars: + changes.append([changeStart, changeEnd, messages.TEXT_SELECTED]) + if oldString.endswith(self.EMBEDDED_OBJECT_CHARACTER) and oldEnd == changeStart: + # There's a possibility that we have a link spanning multiple lines. If so, + # we want to present the continuation that just became selected. + child = self.findChildAtOffset(obj, oldEnd - 1) + self.handleTextSelectionChange(child, False) + else: + changes.append([changeStart, changeEnd, messages.TEXT_UNSELECTED]) + if newString.endswith(self.EMBEDDED_OBJECT_CHARACTER): + # There's a possibility that we have a link spanning multiple lines. If so, + # we want to present the continuation that just became unselected. + child = self.findChildAtOffset(obj, newEnd - 1) + self.handleTextSelectionChange(child, False) + + speakMessage = speakMessage and not _settingsManager.getSetting('onlySpeakDisplayedText') + text = obj.queryText() + for start, end, message in changes: + string = text.getText(start, end) + endsWithChild = string.endswith(self.EMBEDDED_OBJECT_CHARACTER) + if endsWithChild: + end -= 1 + + self._script.sayPhrase(obj, start, end) + if speakMessage and not endsWithChild: + self._script.speakMessage(message, interrupt=False) + + if endsWithChild: + child = self.findChildAtOffset(obj, end) + self.handleTextSelectionChange(child, speakMessage) + + return True + + def _getCtrlShiftSelectionsStrings(self): + """Hacky and to-be-obsoleted method.""" + return [messages.PARAGRAPH_SELECTED_DOWN, + messages.PARAGRAPH_UNSELECTED_DOWN, + messages.PARAGRAPH_SELECTED_UP, + messages.PARAGRAPH_UNSELECTED_UP] + + def _speakTextSelectionState(self, nSelections): + """Hacky and to-be-obsoleted method.""" + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return False + + eventStr, mods = self.lastKeyAndModifiers() + isControlKey = mods & keybindings.CTRL_MODIFIER_MASK + isShiftKey = mods & keybindings.SHIFT_MODIFIER_MASK + selectedText = nSelections > 0 + + line = None + if (eventStr == "Page_Down") and isShiftKey and isControlKey: + line = messages.LINE_SELECTED_RIGHT + elif (eventStr == "Page_Up") and isShiftKey and isControlKey: + line = messages.LINE_SELECTED_LEFT + elif (eventStr == "Page_Down") and isShiftKey and not isControlKey: + if selectedText: + line = messages.PAGE_SELECTED_DOWN + else: + line = messages.PAGE_UNSELECTED_DOWN + elif (eventStr == "Page_Up") and isShiftKey and not isControlKey: + if selectedText: + line = messages.PAGE_SELECTED_UP + else: + line = messages.PAGE_UNSELECTED_UP + elif (eventStr == "Down") and isShiftKey and isControlKey: + strings = self._getCtrlShiftSelectionsStrings() + if selectedText: + line = strings[0] + else: + line = strings[1] + elif (eventStr == "Up") and isShiftKey and isControlKey: + strings = self._getCtrlShiftSelectionsStrings() + if selectedText: + line = strings[2] + else: + line = strings[3] + elif (eventStr == "Home") and isShiftKey and isControlKey: + if selectedText: + line = messages.DOCUMENT_SELECTED_UP + else: + line = messages.DOCUMENT_UNSELECTED_UP + elif (eventStr == "End") and isShiftKey and isControlKey: + if selectedText: + line = messages.DOCUMENT_SELECTED_DOWN + else: + line = messages.DOCUMENT_SELECTED_UP + elif self.lastInputEventWasSelectAll() and selectedText: + if not self._script.pointOfReference.get('entireDocumentSelected'): + self._script.pointOfReference['entireDocumentSelected'] = True + line = messages.DOCUMENT_SELECTED_ALL + else: + return True + + if not line: + return False + + if line != self._script.pointOfReference.get('last-selection-message'): + self._script.pointOfReference['last-selection-message'] = line + self._script.speakMessage(line) + + return True + + def shouldInterruptForLocusOfFocusChange(self, oldLocusOfFocus, newLocusOfFocus, event=None): + msg = "SCRIPT UTILITIES: Not interrupting for locusOfFocus change: " + if event is None: + msg += "event is None" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if event is not None and event.type.startswith("object:active-descendant-changed"): + return self._script.stopSpeechOnActiveDescendantChanged(event) + + if AXUtilities.is_table_cell(oldLocusOfFocus) and AXUtilities.is_text(newLocusOfFocus) \ + and AXUtilities.is_editable(newLocusOfFocus): + msg += "suspected editable cell" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not AXUtilities.is_menu_related(newLocusOfFocus) \ + and (AXUtilities.is_check_menu_item(oldLocusOfFocus) \ + or AXUtilities.is_radio_menu_item(oldLocusOfFocus)): + msg += "suspected menuitem state change" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if AXObject.is_ancestor(newLocusOfFocus, oldLocusOfFocus): + msg += "old locusOfFocus is ancestor of new locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def isOld(target): + return target == oldLocusOfFocus + + def isNew(target): + return target == newLocusOfFocus + + if AXObject.get_relation_targets(newLocusOfFocus, + Atspi.RelationType.CONTROLLER_FOR, isOld): + msg += "new locusOfFocus controls old locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + if AXObject.get_relation_targets(oldLocusOfFocus, + Atspi.RelationType.CONTROLLER_FOR, isNew): + msg += "old locusOfFocus controls new locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + return True + + def stringsAreRedundant(self, str1, str2, threshold=0.5): + if not (str1 and str2): + return False + + similarity = round(SequenceMatcher(None, str1.lower(), str2.lower()).ratio(), 2) + msg = ( + f"SCRIPT UTILITIES: Similarity between '{str1}', '{str2}': {similarity} " + f"(threshold: {threshold})" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return similarity >= threshold diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/__init__.py new file mode 100644 index 0000000..782103c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script.py new file mode 100644 index 0000000..e7e0add --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import cthulhu.scripts.default as default +import cthulhu.cthulhu_state as cthulhu_state + +from .script_utilities import Utilities + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + default.Script.__init__(self, app) + self._last_seek_value = 0 + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def onValueChanged(self, event): + obj = event.source + if self.utilities.isSeekSlider(obj): + value = obj.queryValue() + current_value = int(value.currentValue)/1000 + if current_value in range(self._last_seek_value, self._last_seek_value + 4): + if self.utilities.isSameObject(obj, cthulhu_state.locusOfFocus): + self.updateBraille(obj) + return + + self._last_seek_value = current_value + + default.Script.onValueChanged(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script_utilities.py new file mode 100644 index 0000000..3f833d3 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Banshee/script_utilities.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import cthulhu.script_utilities as script_utilities +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + """Creates an instance of the Utilities class. + + Arguments: + - script: the script with which this instance is associated. + """ + + script_utilities.Utilities.__init__(self, script) + + def _formatDuration(self, s): + seconds = '%02d' % (s%60) + minutes = '%02d' % (s/60) + hours = '%02d' % (s/3600) + duration = [minutes, seconds] + if hours != '00': + duration.insert(0, hours) + + return ':'.join(duration) + + def isSeekSlider(self, obj): + return AXObject.find_ancestor(obj, AXUtilities.is_tool_bar) is not None + + def textForValue(self, obj): + if not self.isSeekSlider(obj): + return script_utilities.Utilities.textForValue(self, obj) + + try: + value = obj.queryValue() + except NotImplementedError: + return script_utilities.Utilities.textForValue(self, obj) + else: + return self._formatDuration(int(value.currentValue)/1000) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/script.py new file mode 100644 index 0000000..5b9b22e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Eclipse/script.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Eclipse.""" +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Informal Informatica LTDA." +__license__ = "LGPL" + + +import cthulhu.debug as debug +import cthulhu.cthulhu as cthulhu +import cthulhu.scripts.toolkits.GAIL as GAIL +from cthulhu.ax_utilities import AXUtilities + +######################################################################## +# # +# The Eclipse script class. # +# # +######################################################################## +class Script(GAIL.Script): + + def __init__(self, app): + """Creates a new script for the given application.""" + GAIL.Script.__init__(self, app) + self.movementKeys = ["Up", "Down", "Left", "Right", "Page_Up", + "Page_Down", "Home", "End"] + + def _presentTextAtNewCaretPosition(self, event, otherObj=None): + """Updates braille and outputs speech for the event.source or the + otherObj. Overridden here so that we can give more feedback to user. + """ + + # Let the default script's normal behavior do its thing + # + GAIL.Script._presentTextAtNewCaretPosition(self, event, otherObj) + + # check if the obj was spoken in the default script + lastKey, mods = self.utilities.lastKeyAndModifiers() + if lastKey in self.movementKeys: + # already spoken in default script + return + + obj = otherObj or event.source + if AXUtilities.is_single_line(obj): + return + + # if Tab key is pressed and there is text selected, we must announce + # the text selected because probably we are in a parameter list + # and we are jumping between the parameters with the tab key. + hasSelection = False + if lastKey in ["Tab", "ISO_Left_Tab"]: + [text, startOffset, endOffset] = self.utilities.selectedText(obj) + hasSelection = endOffset > 0 + + if hasSelection: + self.sayPhrase(obj, startOffset, endOffset) + else: + self.sayLine(obj) + + self._saveLastTextPosition(obj) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # NOTE: This event type is deprecated and Cthulhu should no longer use it. + # This callback remains just to handle bugs in applications and toolkits. + if AXUtilities.is_panel(event.source): + cthulhu.setLocusOfFocus(event, event.source) + return + + if AXUtilities.is_text(event.source) \ + and self.utilities.lastInputEventWasUnmodifiedArrow() \ + and self.utilities.inMenu(): + msg = "ECLIPSE: Ignoring event. In menu." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().onFocus(event) + + def onTextInserted(self, event): + """Called whenever text is inserted into an object. Overridden here + so that we can avoid speaking text when caret moves after new text + is inserted. + + Arguments: + - event: the Event + """ + + if self.utilities.isTextArea(event.source): + length = event.source.queryText().characterCount + if event.detail1 == 0 and event.detail2 == length: + # seems to be generated by a reformat (ctrl+shift+f) + # or by commenting some block (ctrl+/). + # if not discarded, cthulhu will speak all the text of the file. + return + # Let the default script's normal behavior do its thing + GAIL.Script.onTextInserted(self, event) + self._saveLastTextPosition(event.source) + + def onTextDeleted(self, event): + """Called whenever text is deleted from an object. Overridden here + so that we can avoid speaking text when caret moves after new text + is deleted. + + Arguments: + - event: the Event + """ + + # Let the default script's normal behavior do its thing + # + GAIL.Script.onTextDeleted(self, event) + self._saveLastTextPosition(event.source) + + def _saveLastTextPosition(self, obj): + if self.utilities.isTextArea(obj): + self._saveLastCursorPosition(obj, obj.queryText().caretOffset) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + # Sometimes Eclipse fires an object:selection-changed event for non-focused + # containers. We don't want to present those. The exception is the MenuBar. + if not (AXUtilities.is_focused(event.source) or AXUtilities.is_menu_bar(event.source)): + return + + GAIL.Script.onSelectionChanged(self, event) + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/__init__.py new file mode 100644 index 0000000..c5216a2 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for SeaMonkey.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/script.py new file mode 100644 index 0000000..d3301d5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/SeaMonkey/script.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for SeaMonkey.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import cmdnames +from cthulhu import debug +from cthulhu import input_event +from cthulhu import cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.scripts.toolkits import Gecko + + +class Script(Gecko.Script): + + def __init__(self, app): + super().__init__(app) + + def setupInputEventHandlers(self): + super().setupInputEventHandlers() + + self.inputEventHandlers["togglePresentationModeHandler"] = \ + input_event.InputEventHandler( + Script.togglePresentationMode, + cmdnames.TOGGLE_PRESENTATION_MODE) + + self.inputEventHandlers["enableStickyFocusModeHandler"] = \ + input_event.InputEventHandler( + Script.enableStickyFocusMode, + cmdnames.SET_FOCUS_MODE_STICKY) + + self.inputEventHandlers["enableStickyBrowseModeHandler"] = \ + input_event.InputEventHandler( + Script.enableStickyBrowseMode, + cmdnames.SET_BROWSE_MODE_STICKY) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + + if self.utilities.isContentEditableWithEmbeddedObjects(event.source): + msg = "SEAMONKEY: Ignoring, event source is content editable" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + table = self.utilities.getTable(cthulhu_state.locusOfFocus) + if table and not self.utilities.isTextDocumentTable(table): + tokens = ["SEAMONKEY: Ignoring, locusOfFocus is", cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + super().onBusyChanged(event) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # We should get proper state-changed events for these. + if self.utilities.inDocumentContent(event.source): + return + + focusRole = AXObject.get_role(cthulhu_state.locusOfFocus) + if focusRole != Atspi.Role.ENTRY or not self.utilities.inDocumentContent(): + super().onFocus(event) + return + + if AXObject.get_role(event.source) == Atspi.Role.MENU: + msg = "SEAMONKEY: Non-document menu claimed focus from document entry" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if self.utilities.lastInputEventWasPrintableKey(): + msg = "SEAMONKEY: Ignoring, believed to be result of printable input" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().onFocus(event) + + def useFocusMode(self, obj, prevObj=None): + if self.utilities.isEditableMessage(obj): + tokens = ["SEAMONKEY: Using focus mode for editable message", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + tokens = ["SEAMONKEY:", obj, "is not an editable message."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return super().useFocusMode(obj, prevObj) + + def enableStickyBrowseMode(self, inputEvent, forceMessage=False): + if self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return + + super().enableStickyBrowseMode(inputEvent, forceMessage) + + def enableStickyFocusMode(self, inputEvent, forceMessage=False): + if self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return + + super().enableStickyFocusMode(inputEvent, forceMessage) + + def togglePresentationMode(self, inputEvent, documentFrame=None): + if self._inFocusMode \ + and self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return + + super().togglePresentationMode(inputEvent, documentFrame) + + def useStructuralNavigationModel(self, debugOutput=True): + if self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return False + + return super().useStructuralNavigationModel(debugOutput) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/__init__.py new file mode 100644 index 0000000..95d8f9c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/__init__.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" Custom script for Thunderbird 3. +""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/script.py new file mode 100644 index 0000000..482dc06 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/script.py @@ -0,0 +1,396 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Thunderbird.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import cthulhu.cthulhu as cthulhu +import cthulhu.cmdnames as cmdnames +import cthulhu.debug as debug +import cthulhu.input_event as input_event +import cthulhu.scripts.default as default +import cthulhu.settings_manager as settings_manager +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.toolkits.Gecko as Gecko +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .spellcheck import SpellCheck + +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# The Thunderbird script class. # +# # +######################################################################## + +class Script(Gecko.Script): + """The script for Thunderbird.""" + + def __init__(self, app): + """ Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + # Store the last autocompleted string for the address fields + # so that we're not too 'chatty'. See bug #533042. + # + self._lastAutoComplete = "" + + if _settingsManager.getSetting('sayAllOnLoad') is None: + _settingsManager.setSetting('sayAllOnLoad', False) + if _settingsManager.getSetting('pageSummaryOnLoad') is None: + _settingsManager.setSetting('pageSummaryOnLoad', False) + + super().__init__(app) + + def setupInputEventHandlers(self): + super().setupInputEventHandlers() + + self.inputEventHandlers["togglePresentationModeHandler"] = \ + input_event.InputEventHandler( + Script.togglePresentationMode, + cmdnames.TOGGLE_PRESENTATION_MODE) + + self.inputEventHandlers["enableStickyFocusModeHandler"] = \ + input_event.InputEventHandler( + Script.enableStickyFocusMode, + cmdnames.SET_FOCUS_MODE_STICKY) + + self.inputEventHandlers["enableStickyBrowseModeHandler"] = \ + input_event.InputEventHandler( + Script.enableStickyBrowseMode, + cmdnames.SET_BROWSE_MODE_STICKY) + + def getSpellCheck(self): + """Returns the spellcheck support for this script.""" + + return SpellCheck(self) + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application.""" + + grid = super().getAppPreferencesGUI() + + self._sayAllOnLoadCheckButton.set_active( + _settingsManager.getSetting('sayAllOnLoad')) + self._pageSummaryOnLoadCheckButton.set_active( + _settingsManager.getSetting('pageSummaryOnLoad')) + + spellcheck = self.spellcheck.getAppPreferencesGUI() + grid.attach(spellcheck, 0, len(grid.get_children()), 1, 1) + grid.show_all() + + return grid + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + prefs = super().getPreferencesFromGUI() + prefs['sayAllOnLoad'] = self._sayAllOnLoadCheckButton.get_active() + prefs['pageSummaryOnLoad'] = self._pageSummaryOnLoadCheckButton.get_active() + prefs.update(self.spellcheck.getPreferencesFromGUI()) + + return prefs + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if self.spellcheck.isSuggestionsItem(newFocus): + includeLabel = not self.spellcheck.isSuggestionsItem(oldFocus) + cthulhu.emitRegionChanged(newFocus) + self.updateBraille(newFocus) + self.spellcheck.presentSuggestionListItem(includeLabel=includeLabel) + return + + super().locusOfFocusChanged(event, oldFocus, newFocus) + + def useFocusMode(self, obj, prevObj=None): + if self.utilities.isEditableMessage(obj): + tokens = ["THUNDERBIRD: Using focus mode for editable message", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + tokens = ["THUNDERBIRD:", obj, "is not an editable message."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return super().useFocusMode(obj, prevObj) + + def enableStickyBrowseMode(self, inputEvent, forceMessage=False): + if self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return + + super().enableStickyBrowseMode(inputEvent, forceMessage) + + def enableStickyFocusMode(self, inputEvent, forceMessage=False): + if self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return + + super().enableStickyFocusMode(inputEvent, forceMessage) + + def togglePresentationMode(self, inputEvent, documentFrame=None): + if self._inFocusMode and self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return + + super().togglePresentationMode(inputEvent, documentFrame) + + def useStructuralNavigationModel(self, debugOutput=True): + """Returns True if structural navigation should be enabled here.""" + + if self.utilities.isEditableMessage(cthulhu_state.locusOfFocus): + return False + + return super().useStructuralNavigationModel(debugOutput) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + return + + self._lastAutoComplete = "" + obj = event.source + if self.spellcheck.isAutoFocusEvent(event): + cthulhu.setLocusOfFocus(event, event.source, False) + self.updateBraille(cthulhu_state.locusOfFocus) + + if not self.utilities.inDocumentContent(obj): + super().onFocusedChanged(event) + return + + if self.utilities.isEditableMessage(obj): + super().onFocusedChanged(event) + return + + super().onFocusedChanged(event) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + + if self.utilities.isEditableMessage(event.source): + return + + if self.inFocusMode(): + return + + obj = event.source + if self.utilities.isDocument(obj) and not event.detail1: + if AXObject.get_name(cthulhu_state.locusOfFocus) \ + and (AXUtilities.is_frame(cthulhu_state.locusOfFocus) \ + or AXUtilities.is_page_tab(cthulhu_state.locusOfFocus)): + cthulhu.setLocusOfFocus(event, event.source, False) + + if self.utilities.inDocumentContent(): + self.speakMessage(AXObject.get_name(obj)) + self._presentMessage(obj) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if self.utilities.isEditableMessage(event.source): + if event.detail1 == -1: + return + self.spellcheck.setDocumentPosition(event.source, event.detail1) + if self.spellcheck.isActive(): + return + + super().onCaretMoved(event) + + def onSelectionChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + # We present changes when the list has focus via focus-changed events. + if event.source == self.spellcheck.getSuggestionsList(): + return + + parent = AXObject.get_parent(event.source) + if AXUtilities.is_combo_box(parent) and not AXUtilities.is_focused(parent): + return + + super().onSelectionChanged(event) + + def onSensitiveChanged(self, event): + """Callback for object:state-changed:sensitive accessibility events.""" + + if event.source == self.spellcheck.getChangeToEntry() \ + and self.spellcheck.presentCompletionMessage(): + return + + super().onSensitiveChanged(event) + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + # TODO - JD: Once there are separate scripts for the Gecko toolkit + # and the Firefox browser, this method can be deleted. It's here + # right now just to prevent the Gecko script from presenting non- + # existent browsery autocompletes for Thunderbird. + + if event.detail1 and self.utilities.isMenuWithNoSelectedChild(event.source) \ + and cthulhu_state.activeWindow == self.utilities.topLevelObject(event.source): + self.presentObject(event.source) + cthulhu.setLocusOfFocus(event, event.source, False) + return + + default.Script.onShowingChanged(self, event) + + def onTextDeleted(self, event): + """Called whenever text is from an object. + + Arguments: + - event: the Event + """ + + if AXUtilities.is_label(event.source) \ + and AXUtilities.is_status_bar(AXObject.get_parent(event.source)): + return + + super().onTextDeleted(event) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + parent = AXObject.get_parent(event.source) + if AXUtilities.is_label(event.source) and AXUtilities.is_status_bar(parent): + return + + if len(event.any_data) > 1 and event.source == self.spellcheck.getChangeToEntry(): + return + + isSystemEvent = event.type.endswith("system") + + # Try to stop unwanted chatter when a message is being replied to. + # See bgo#618484. + if isSystemEvent and self.utilities.isEditableMessage(event.source): + return + + # Speak the autocompleted text, but only if it is different + # address so that we're not too "chatty." See bug #533042. + if AXUtilities.is_autocomplete(parent): + if len(event.any_data) == 1: + default.Script.onTextInserted(self, event) + return + + if self._lastAutoComplete and self._lastAutoComplete in event.any_data: + return + + # Mozilla cannot seem to get their ":system" suffix right + # to save their lives, so we'll add yet another sad hack. + try: + text = event.source.queryText() + except Exception: + hasSelection = False + else: + hasSelection = text.getNSelections() > 0 + if hasSelection or isSystemEvent: + voice = self.speechGenerator.voice(obj=event.source, string=event.any_data) + self.speakMessage(event.any_data, voice=voice) + self._lastAutoComplete = event.any_data + return + + super().onTextInserted(event) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + obj = event.source + spellCheckEntry = self.spellcheck.getChangeToEntry() + if obj == spellCheckEntry: + return + + if self.utilities.isEditableMessage(obj) and self.spellcheck.isActive(): + text = obj.queryText() + selStart, selEnd = text.getSelection(0) + self.spellcheck.setDocumentPosition(obj, selStart) + return + + super().onTextSelectionChanged(event) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if AXObject.get_name(event.source) == self.spellcheck.getMisspelledWord(): + self.spellcheck.presentErrorDetails() + return + + if not self.utilities.lastInputEventWasDelete() \ + or not self.utilities.isDocument(event.source): + return + + super().onNameChanged(event) + + def _presentMessage(self, documentFrame): + """Presents the first line of the message, or the entire message, + depending on the user's sayAllOnLoad setting.""" + + [obj, offset] = self.utilities.findFirstCaretContext(documentFrame, 0) + self.utilities.setCaretPosition(obj, offset) + self.updateBraille(obj) + + if _settingsManager.getSetting('pageSummaryOnLoad'): + tokens = ["THUNDERBIRD: Getting page summary for obj", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + summary = self.utilities.getPageSummary(obj) + if summary: + self.presentMessage(summary) + + if not _settingsManager.getSetting('sayAllOnLoad'): + msg = "THUNDERBIRD: SayAllOnLoad is False. Presenting line." + debug.printMessage(debug.LEVEL_INFO, msg, True) + contents = self.utilities.getLineContentsAtOffset(obj, offset) + self.speakContents(contents) + return + + if _settingsManager.getSetting('enableSpeech'): + msg = "THUNDERBIRD: SayAllOnLoad is True and speech is enabled" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayAll(None) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + super().onWindowActivated(event) + if not self.spellcheck.isCheckWindow(event.source): + self.spellcheck.deactivate() + return + + self.spellcheck.presentErrorDetails() + cthulhu.setLocusOfFocus(None, self.spellcheck.getChangeToEntry(), False) + self.updateBraille(cthulhu_state.locusOfFocus) + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + super().onWindowDeactivated(event) + self.spellcheck.deactivate() + self.utilities.clearContentCache() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/spellcheck.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/spellcheck.py new file mode 100644 index 0000000..abbb8a1 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/Thunderbird/spellcheck.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Customized support for spellcheck in Thunderbird.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.spellcheck as spellcheck +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class SpellCheck(spellcheck.SpellCheck): + + def __init__(self, script): + super(SpellCheck, self).__init__(script) + + def isAutoFocusEvent(self, event): + if event.source != self._changeToEntry: + return False + + if not AXUtilities.is_push_button(cthulhu_state.locusOfFocus): + return False + + lastKey, mods = self._script.utilities.lastKeyAndModifiers() + keys = self._script.utilities.mnemonicShortcutAccelerator(cthulhu_state.locusOfFocus) + for key in keys: + if key.endswith(lastKey.upper()): + return True + + return False + + def _isCandidateWindow(self, window): + if not AXUtilities.is_dialog(window): + return False + + def isNonSpellCheckChild(x): + return AXUtilities.is_page_tab_list(x) or AXUtilities.is_split_pane(x) + + if AXObject.find_descendant(window, isNonSpellCheckChild): + return False + + return True + + def _findChangeToEntry(self, root): + def isSingleLineEntry(x): + return AXUtilities.is_entry(x) and AXUtilities.is_single_line(x) + + return AXObject.find_descendant(root, isSingleLineEntry) + + def _findErrorWidget(self, root): + def isError(x): + return AXUtilities.is_label(x) \ + and ":" not in AXObject.get_name(x) \ + and not AXObject.get_relations(x) + + return AXObject.find_descendant(root, isError) + + def _findSuggestionsList(self, root): + def isList(x): + if not AXObject.supports_selection(x): + return False + return AXUtilities.is_list_box(x) or AXUtilities.is_list(x) + + return AXObject.find_descendant(root, isList) + + def _getSuggestionIndexAndPosition(self, suggestion): + attrs = self._script.utilities.objectAttributes(suggestion) + index = attrs.get("posinset") + total = attrs.get("setsize") + if index is None or total is None: + return super()._getSuggestionIndexAndPosition(suggestion) + + return int(index), int(total) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/__init__.py new file mode 100644 index 0000000..4fa84d8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/__init__.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__all__ = ['Banshee', + 'Eclipse', + 'epiphany', + 'evince', + 'evolution', + 'gajim', + 'gcalctool', + 'gedit', + 'gnome-documents', + 'gnome-shell', + 'kwin', + 'notification-daemon', + 'notify-osd', + 'pidgin', + 'soffice', + 'SeaMonkey', + 'smuxi-frontend-gnome', + 'Thunderbird', + 'xfwm4'] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/__init__.py new file mode 100644 index 0000000..74133ed --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/__init__.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for epiphany.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 + +from .script import Script + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/script.py new file mode 100644 index 0000000..13db3cc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/epiphany/script.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for epiphany.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.cthulhu as cthulhu +import cthulhu.scripts.toolkits.gtk as gtk +import cthulhu.scripts.toolkits.WebKitGtk as WebKitGtk + +class Script(WebKitGtk.Script): + + def __init__(self, app): + WebKitGtk.Script.__init__(self, app) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + gtk.Script.onWindowActivated(self, event) + + obj, offset = self.utilities.getCaretContext() + if obj: + cthulhu.setLocusOfFocus(None, obj) + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + gtk.Script.onWindowDeactivated(self, event) + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/__init__.py new file mode 100644 index 0000000..92d06d1 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for evince.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/script.py new file mode 100644 index 0000000..b8c2b0e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evince/script.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for evince.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013 The Cthulhu Team." +__license__ = "LGPL" + +import cthulhu.keybindings as keybindings +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.toolkits.gtk as gtk +from cthulhu.ax_utilities import AXUtilities +from cthulhu.structural_navigation import StructuralNavigation + + +######################################################################## +# # +# The evince script class. # +# # +######################################################################## + +class Script(gtk.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + gtk.Script.__init__(self, app) + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings.""" + + gtk.Script.setupInputEventHandlers(self) + self.inputEventHandlers.update( + self.structuralNavigation.inputEventHandlers) + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + keyBindings = keybindings.KeyBindings() + bindings = self.structuralNavigation.keyBindings + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + return keyBindings + + def getStructuralNavigation(self): + """Returns the 'structural navigation' class for this script.""" + + types = self.getEnabledStructuralNavigationTypes() + return StructuralNavigation(self, types, True) + + def getEnabledStructuralNavigationTypes(self): + """Returns a list of the structural navigation object types + enabled in this script.""" + + enabledTypes = [StructuralNavigation.BUTTON, + StructuralNavigation.CHECK_BOX, + StructuralNavigation.COMBO_BOX, + StructuralNavigation.ENTRY, + StructuralNavigation.FORM_FIELD, + StructuralNavigation.HEADING, + StructuralNavigation.LINK, + StructuralNavigation.LIST, + StructuralNavigation.LIST_ITEM, + StructuralNavigation.PARAGRAPH, + StructuralNavigation.RADIO_BUTTON, + StructuralNavigation.TABLE, + StructuralNavigation.TABLE_CELL, + StructuralNavigation.UNVISITED_LINK, + StructuralNavigation.VISITED_LINK] + + return enabledTypes + + def useStructuralNavigationModel(self, debugOutput=True): + """Returns True if we should do our own structural navigation.""" + + if not self.structuralNavigation.enabled: + return False + + if AXUtilities.is_editable(cthulhu_state.locusOfFocus): + return False + + return True + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + obj = event.source + if AXUtilities.is_focused(obj): + cthulhu.setLocusOfFocus(event, event.source, False) + + gtk.Script.onCaretMoved(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/__init__.py new file mode 100644 index 0000000..87978a5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Evolution.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/braille_generator.py new file mode 100644 index 0000000..666d57e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/braille_generator.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2015 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.braille as braille +import cthulhu.braille_generator as braille_generator +import cthulhu.scripts.toolkits.WebKitGtk as WebKitGtk + +class BrailleGenerator(WebKitGtk.BrailleGenerator, braille_generator.BrailleGenerator): + + def __init__(self, script): + super().__init__(script) + self._cache = {} + + def _isMessageListToggleCell(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isMessageListToggleCell") + if rv is None: + rv = self._script.utilities.isMessageListToggleCell(obj) + cached["isMessageListToggleCell"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _generateRealActiveDescendantDisplayedText(self, obj, **args): + if self._isMessageListToggleCell(obj): + return [] + + return super()._generateRealActiveDescendantDisplayedText(obj, **args) + + def generateBraille(self, obj, **args): + self._cache = {} + result, focusedRegion = super().generateBraille(obj, **args) + self._cache = {} + + if not result or focusedRegion != result[0]: + return [result, focusedRegion] + + def hasObj(x): + return isinstance(x, (braille.Component, braille.Text)) + + def isObj(x): + return self._script.utilities.isSameObject(obj, x.accessible) + + matches = [r for r in result if hasObj(r) and isObj(r)] + if matches: + focusedRegion = matches[0] + + return [result, focusedRegion] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script.py new file mode 100644 index 0000000..9630530 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Evolution.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2013 Igalia, S.L." +__license__ = "LGPL" + + +import cthulhu.debug as debug +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.toolkits.gtk as gtk +import cthulhu.scripts.toolkits.WebKitGtk as WebKitGtk +import cthulhu.settings_manager as settings_manager +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .braille_generator import BrailleGenerator +from .speech_generator import SpeechGenerator +from .script_utilities import Utilities + +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# The Evolution script class. # +# # +######################################################################## + +class Script(WebKitGtk.Script, gtk.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + if _settingsManager.getSetting('sayAllOnLoad') is None: + _settingsManager.setSetting('sayAllOnLoad', False) + + super().__init__(app) + self.presentIfInactive = False + + def getBrailleGenerator(self): + return BrailleGenerator(self) + + def getSpeechGenerator(self): + return SpeechGenerator(self) + + def getUtilities(self): + return Utilities(self) + + def isActivatableEvent(self, event): + """Returns True if the given event is one that should cause this + script to become the active script. This is only a hint to + the focus tracking manager and it is not guaranteed this + request will be honored. Note that by the time the focus + tracking manager calls this method, it thinks the script + should become active. This is an opportunity for the script + to say it shouldn't. + """ + + if event.type.startswith("focus:") and AXUtilities.is_menu(event.source): + return True + + window = self.utilities.topLevelObject(event.source) + if not AXUtilities.is_active(window): + return False + + return True + + def stopSpeechOnActiveDescendantChanged(self, event): + """Whether or not speech should be stopped prior to setting the + locusOfFocus in onActiveDescendantChanged. + + Arguments: + - event: the Event + + Returns True if speech should be stopped; False otherwise. + """ + + return False + + ######################################################################## + # # + # AT-SPI OBJECT EVENT HANDLERS # + # # + ######################################################################## + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if not event.any_data: + msg = "EVOLUTION: Ignoring event. No any_data." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.utilities.isComposeAutocomplete(event.source): + if AXUtilities.is_selected(event.any_data): + msg = "EVOLUTION: Source is compose autocomplete with selected child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.any_data) + else: + msg = "EVOLUTION: Source is compose autocomplete without selected child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source) + return + + if AXUtilities.is_table_cell(cthulhu_state.locusOfFocus): + table = AXObject.find_ancestor( + cthulhu_state.locusOfFocus, AXUtilities.is_tree_or_tree_table) + if table is not None and table != event.source: + msg = "EVOLUTION: Event is from a different tree or tree table." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + child = AXObject.get_active_descendant_checked(event.source, event.any_data) + if child is not None and child != event.any_data: + tokens = ["EVOLUTION: Bogus any_data suspected. Setting focus to", child] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, child) + return + + msg = "EVOLUTION: Passing event to super class for processing." + debug.printMessage(debug.LEVEL_INFO, msg, True) + super().onActiveDescendantChanged(event) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + pass + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + if self.utilities.isWebKitGtk(event.source): + return + + # This is some mystery child of the 'Messages' panel which fails to show + # up in the hierarchy or emit object:state-changed:focused events. + if AXUtilities.is_layered_pane(event.source): + obj = self.utilities.realActiveDescendant(event.source) + cthulhu.setLocusOfFocus(event, obj) + return + + gtk.Script.onFocus(self, event) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if self.utilities.isWebKitGtk(event.source): + return + + gtk.Script.onNameChanged(self, event) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if AXUtilities.is_combo_box(event.source) \ + and not AXUtilities.is_focused(event.source): + return + + gtk.Script.onSelectionChanged(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script_utilities.py new file mode 100644 index 0000000..53709ba --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/script_utilities.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2015 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.scripts.toolkits.gtk as gtk +import cthulhu.scripts.toolkits.WebKitGtk as WebKitGtk +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(WebKitGtk.Utilities, gtk.Utilities): + + def __init__(self, script): + super().__init__(script) + + def isComposeMessageBody(self, obj): + if not AXUtilities.is_editable(obj): + return False + + return self.isEmbeddedDocument(obj) + + def isReceivedMessage(self, obj): + if AXUtilities.is_editable(obj): + return False + + return self.isEmbeddedDocument(obj) + + def isReceivedMessageHeader(self, obj): + if not AXUtilities.is_table(obj): + return False + + return self.isReceivedMessage(AXObject.get_parent(obj)) + + def isReceivedMessageContent(self, obj): + if not AXUtilities.is_section(obj): + return False + + return self.isReceivedMessage(AXObject.get_parent(obj)) + + def isComposeAutocomplete(self, obj): + if not AXUtilities.is_table(obj): + return False + + if not AXUtilities.manages_descendants(obj): + return False + + return AXUtilities.is_window(self.topLevelObject(obj)) + + def findMessageBodyChild(self, root): + candidate = AXObject.find_descendant(root, self.isDocument) + if self.isEmbeddedDocument(candidate): + return self.findMessageBodyChild(candidate) + + return candidate + + def isMessageListStatusCell(self, obj): + if not self.isMessageListToggleCell(obj): + return False + + header = self.columnHeaderForCell(obj) + return header and AXObject.get_name(header) != AXObject.get_name(obj) + + def isMessageListToggleCell(self, obj): + if self.isWebKitGtk(obj): + return False + + if not gtk.Utilities.hasMeaningfulToggleAction(self, obj): + return False + + if not AXObject.get_name(obj): + return False + + return True + + def realActiveDescendant(self, obj): + if self.isWebKitGtk(obj): + return super().realActiveDescendant(obj) + + # This is some mystery child of the 'Messages' panel which fails to show + # up in the hierarchy or emit object:state-changed:focused events. + if AXUtilities.is_layered_pane(obj): + return AXObject.find_descendant(obj, AXUtilities.is_tree_table) or obj + + return gtk.Utilities.realActiveDescendant(self, obj) + + def setCaretAtStart(self, obj): + if self.isReceivedMessageContent(obj): + obj = self.findMessageBodyChild(obj) or obj + + child, index = super().setCaretAtStart(obj) + if child and index == -1: + child, index = super().setCaretAtStart(child) + + return child, index + + def treatAsBrowser(self, obj): + if not self.isEmbeddedDocument(obj): + return False + + if AXObject.find_ancestor(obj, AXUtilities.is_split_pane) is not None: + return False + + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/speech_generator.py new file mode 100644 index 0000000..0625ed9 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/evolution/speech_generator.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2015 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.scripts.toolkits.WebKitGtk as WebKitGtk +import cthulhu.speech_generator as speech_generator +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class SpeechGenerator(WebKitGtk.SpeechGenerator, speech_generator.SpeechGenerator): + + def __init__(self, script): + super().__init__(script) + self._cache = {} + + def _isTreeTableCell(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isTreeTableCell") + if rv is None: + rv = AXUtilities.is_tree_table(AXObject.get_parent(obj)) + cached["isTreeTableCell"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _isMessageListStatusCell(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isMessageListStatusCell") + if rv is None: + rv = self._script.utilities.isMessageListStatusCell(obj) + cached["isMessageListStatusCell"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _isMessageListToggleCell(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isMessageListToggleCell") + if rv is None: + rv = self._script.utilities.isMessageListToggleCell(obj) + cached["isMessageListToggleCell"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _isFocused(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isFocused") + if rv is None: + rv = AXUtilities.is_focused(obj) + cached["isFocused"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _isChecked(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isChecked") + if rv is None: + rv = AXUtilities.is_checked(obj) + cached["isChecked"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _isInNewRow(self, obj): + cached = self._cache.get(hash(obj), {}) + rv = cached.get("isInNewRow") + if rv is None: + row, column = self._script.utilities.coordinatesForCell(obj) + lastRow = self._script.pointOfReference.get("lastRow") + rv = row != lastRow + cached["isInNewRow"] = rv + self._cache[hash(obj)] = cached + + return rv + + def _generateCellCheckedState(self, obj, **args): + if self._isMessageListStatusCell(obj): + return [] + + if self._isMessageListToggleCell(obj): + if self._isInNewRow(obj) or not self._isFocused(obj): + return [] + + return super()._generateCellCheckedState(obj, **args) + + def _generateLabel(self, obj, **args): + if self._isMessageListToggleCell(obj): + return [] + + return super()._generateLabel(obj, **args) + + def _generateName(self, obj, **args): + if self._isMessageListToggleCell(obj) \ + and not self._isMessageListStatusCell(obj): + return [] + + return super()._generateName(obj, **args) + + def _generateLabelOrName(self, obj, **args): + if self._isMessageListToggleCell(obj) \ + and not self._isMessageListStatusCell(obj): + return [] + + return super()._generateLabelOrName(obj, **args) + + def _generateRealActiveDescendantDisplayedText(self, obj, **args): + if self._isMessageListToggleCell(obj) \ + and not self._isMessageListStatusCell(obj): + if not self._isChecked(obj): + return [] + if self._isFocused(obj) and not self._isInNewRow(obj): + return [] + + return super()._generateRealActiveDescendantDisplayedText(obj, **args) + + def _generateRoleName(self, obj, **args): + if self._isMessageListToggleCell(obj) and not self._isFocused(obj): + return [] + + return super()._generateRoleName(obj, **args) + + def _generateUnselectedCell(self, obj, **args): + if self._isMessageListToggleCell(obj) or self._isTreeTableCell(obj): + return [] + + return super()._generateUnselectedCell(obj, **args) + + def generateSpeech(self, obj, **args): + self._cache = {} + results = super().generateSpeech(obj, **args) + self._cache = {} + + return results diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/script.py new file mode 100644 index 0000000..e26517c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gajim/script.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Gajim.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.chat as chat +import cthulhu.scripts.default as default +from cthulhu.ax_utilities import AXUtilities + +######################################################################## +# # +# The Empathy script class. # +# # +######################################################################## + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for the given application.""" + + # So we can take an educated guess at identifying the buddy list. + # + self._buddyListAncestries = [[Atspi.Role.TABLE, + Atspi.Role.SCROLL_PANE, + Atspi.Role.FILLER, + Atspi.Role.SPLIT_PANE, + Atspi.Role.FILLER, + Atspi.Role.FRAME]] + + default.Script.__init__(self, app) + + def getChat(self): + """Returns the 'chat' class for this script.""" + + return chat.Chat(self, self._buddyListAncestries) + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings. Here we need to add the + handlers for chat functionality. + """ + + default.Script.setupInputEventHandlers(self) + self.inputEventHandlers.update(self.chat.inputEventHandlers) + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + return self.chat.keyBindings + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application. The chat-related options get + created by the chat module.""" + + return self.chat.getAppPreferencesGUI() + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return self.chat.getPreferencesFromGUI() + + def onTextInserted(self, event): + """Called whenever text is added to an object.""" + + if self.chat.presentInsertedText(event): + return + + default.Script.onTextInserted(self, event) + + def onWindowActivated(self, event): + """Called whenever a toplevel window is activated.""" + + # Hack to "tickle" the accessible hierarchy. Otherwise, the + # events we need to present text added to the chatroom are + # missing. + AXUtilities.find_all_page_tabs(event.source) + default.Script.onWindowActivated(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/__init__.py new file mode 100644 index 0000000..87978a5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Evolution.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/script.py new file mode 100644 index 0000000..9b10f66 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gcalctool/script.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides a custom script for gcalctool.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.scripts.toolkits.gtk as gtk +import cthulhu.messages as messages +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +######################################################################## +# # +# The GCalcTool script class. # +# # +######################################################################## + +class Script(gtk.Script): + + def __init__(self, app): + """Creates a new script for the given application. Callers + should use the getScript factory method instead of calling + this constructor directly. + + Arguments: + - app: the application to create a script for. + """ + + gtk.Script.__init__(self, app) + + self._resultsDisplay = None + self._statusLine = None + + def onWindowActivated(self, event): + """Called whenever one of gcalctool's toplevel windows is activated. + + Arguments: + - event: the window activated Event + """ + + if self._resultsDisplay and self._statusLine: + gtk.Script.onWindowActivated(self, event) + return + + if AXObject.get_role(event.source) != Atspi.Role.FRAME: + gtk.Script.onWindowActivated(self, event) + return + + self._resultsDisplay = AXObject.find_descendant(event.source, AXUtilities.is_editbar) + if not self._resultsDisplay: + self.presentMessage(messages.CALCULATOR_DISPLAY_NOT_FOUND) + + def isStatusLine(x): + return AXObject.get_role(x) == Atspi.Role.TEXT and not AXUtilities.is_editable(x) + + self._statusLine = AXObject.find_descendant(event.source, isStatusLine) + gtk.Script.onWindowActivated(self, event) + + def onTextInserted(self, event): + """Called whenever text is inserted into gcalctool's text display. + + Arguments: + - event: the text inserted Event + """ + + if self.utilities.isSameObject(event.source, self._statusLine): + self.presentMessage(self.utilities.displayedText(self._statusLine)) + return + + gtk.Script.onTextInserted(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/__init__.py new file mode 100644 index 0000000..935e252 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/__init__.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for gedit.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/script.py new file mode 100644 index 0000000..291e7ff --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/script.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for gedit.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.toolkits.gtk as gtk +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities +from .spellcheck import SpellCheck + +class Script(gtk.Script): + + def __init__(self, app): + """Creates a new script for the given application.""" + + gtk.Script.__init__(self, app) + + def getSpellCheck(self): + """Returns the spellcheck for this script.""" + + return SpellCheck(self) + + def getAppPreferencesGUI(self): + """Returns a GtkGrid containing the application unique configuration + GUI items for the current application.""" + + from gi.repository import Gtk + + grid = Gtk.Grid() + grid.set_border_width(12) + grid.attach(self.spellcheck.getAppPreferencesGUI(), 0, 0, 1, 1) + grid.show_all() + + return grid + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return self.spellcheck.getPreferencesFromGUI() + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if self.spellcheck.isSuggestionsItem(newFocus): + includeLabel = not self.spellcheck.isSuggestionsItem(oldFocus) + cthulhu.emitRegionChanged(newFocus) + self.updateBraille(newFocus) + self.spellcheck.presentSuggestionListItem(includeLabel=includeLabel) + return + + super().locusOfFocusChanged(event, oldFocus, newFocus) + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if event.source == self.spellcheck.getSuggestionsList(): + return + + gtk.Script.onActiveDescendantChanged(self, event) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if AXUtilities.is_multi_line(event.source): + self.spellcheck.setDocumentPosition(event.source, event.detail1) + + gtk.Script.onCaretMoved(self, event) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + return + + gtk.Script.onFocusedChanged(self, event) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if not self.spellcheck.isActive(): + gtk.Script.onNameChanged(self, event) + return + + name = AXObject.get_name(event.source) + if name == self.spellcheck.getMisspelledWord(): + self.spellcheck.presentErrorDetails() + return + + parent = AXObject.get_parent(event.source) + if parent != self.spellcheck.getSuggestionsList() \ + or not AXUtilities.is_focused(parent): + return + + entry = self.spellcheck.getChangeToEntry() + if name != self.utilities.displayedText(entry): + return + + # If we're here, the locusOfFocus was in the selection list when + # that list got destroyed and repopulated. Focus is still there. + cthulhu.setLocusOfFocus(event, event.source, False) + self.updateBraille(cthulhu_state.locusOfFocus) + + def onSensitiveChanged(self, event): + """Callback for object:state-changed:sensitive accessibility events.""" + + if event.source == self.spellcheck.getChangeToEntry() \ + and self.spellcheck.presentCompletionMessage(): + return + + gtk.Script.onSensitiveChanged(self, event) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + if event.source == cthulhu_state.locusOfFocus: + gtk.Script.onTextSelectionChanged(self, event) + return + + if not self.utilities.isSearchEntry(cthulhu_state.locusOfFocus, True): + return + + if not self.utilities.isShowingAndVisible(event.source): + return + + # To avoid extreme chattiness. + keyString, mods = self.utilities.lastKeyAndModifiers() + if keyString in ["BackSpace", "Delete"]: + return + + self.sayLine(event.source) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + gtk.Script.onWindowActivated(self, event) + if not self.spellcheck.isCheckWindow(event.source): + return + + self.spellcheck.presentErrorDetails() + cthulhu.setLocusOfFocus(None, self.spellcheck.getChangeToEntry(), False) + self.updateBraille(cthulhu_state.locusOfFocus) + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + gtk.Script.onWindowDeactivated(self, event) + self.spellcheck.deactivate() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/spellcheck.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/spellcheck.py new file mode 100644 index 0000000..78c775d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gedit/spellcheck.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Customized support for spellcheck in Gedit.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.spellcheck as spellcheck +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class SpellCheck(spellcheck.SpellCheck): + + def __init__(self, script): + super(SpellCheck, self).__init__(script) + + def _isCandidateWindow(self, window): + if not window: + return False + + role = AXObject.get_role(window) + if role == Atspi.Role.DIALOG: + return True + if role != Atspi.Role.FRAME: + return False + + if AXObject.find_descendant(window, AXUtilities.is_split_pane): + return False + + return True + + def _findChangeToEntry(self, root): + def isEntry(x): + return AXUtilities.is_text(x) and AXUtilities.is_single_line(x) + + return AXObject.find_descendant(root, isEntry) + + def _findErrorWidget(self, root): + panel = AXObject.find_ancestor(self._changeToEntry, AXUtilities.is_panel) + if panel is None: + return None + + def isError(x): + return AXUtilities.is_label(x) \ + and ":" not in AXObject.get_name(x) and not AXObject.get_relations(x) + + return AXObject.find_descendant(panel, isError) + + def _findSuggestionsList(self, root): + def isTable(x): + return AXUtilities.is_table(x) and AXObject.supports_selection(x) + + return AXObject.find_descendant(root, isTable) + + def _getSuggestionIndexAndPosition(self, suggestion): + index, total = self._script.utilities.getPositionAndSetSize(suggestion) + total -= 1 + return index, total diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/__init__.py new file mode 100644 index 0000000..fc73e57 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for gnome-documents.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script +from .script_utilities import Utilities diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script.py new file mode 100644 index 0000000..f891976 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for gnome-documents.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013 The Cthulhu Team" +__license__ = "LGPL" + +import cthulhu.scripts.toolkits.gtk as gtk +import cthulhu.cthulhu_state as cthulhu_state +from cthulhu.ax_utilities import AXUtilities + +from .speech_generator import SpeechGenerator +from .script_utilities import Utilities + +class Script(gtk.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + gtk.Script.__init__(self, app) + + def getSpeechGenerator(self): + """Returns the speech generator for this script.""" + + return SpeechGenerator(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def onNameChanged(self, event): + """Callback for accessible name change events.""" + + # Present page changes in the previewer. + if AXUtilities.is_label(event.source) \ + and self.utilities.isDocument(cthulhu_state.locusOfFocus): + self.presentMessage(event.any_data) + + # HACK: Reposition the caret offset from the last character to the + # first so that SayAll will say all. + try: + text = cthulhu_state.locusOfFocus.queryText() + except NotImplementedError: + pass + else: + text.setCaretOffset(0) + return self.sayAll(None) + + gtk.Script.onNameChanged(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script_utilities.py new file mode 100644 index 0000000..a889953 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/script_utilities.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013 The Cthulhu Team." +__license__ = "LGPL" + +import cthulhu.scripts.toolkits.gtk as gtk + +class Utilities(gtk.Utilities): + + def __init__(self, script): + gtk.Utilities.__init__(self, script) + + def isReadOnlyTextArea(self, obj): + if self.isDocument(obj): + return False + + return gtk.Utilities.isReadOnlyTextArea(self, obj) + + def isTextArea(self, obj): + if self.isDocument(obj): + return True + + return gtk.Utilities.isTextArea(self, obj) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/speech_generator.py new file mode 100644 index 0000000..c7c026a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-documents/speech_generator.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom speech generator for gnome-documents.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013 The Cthulhu Team" +__license__ = "LGPL" + +import cthulhu.speech_generator as speech_generator + +class SpeechGenerator(speech_generator.SpeechGenerator): + + def __init__(self, script): + speech_generator.SpeechGenerator.__init__(self, script) + + def _generateUnselectedCell(self, obj, **args): + # There are a number of objects in gnome-documents which claim to + # be selectable, but cannot actually be selected. Until we find and + # fix those issues, this will keep Cthulhu from constantly tacking on + # "not selected" when presenting these objects. + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/formatting.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/formatting.py new file mode 100644 index 0000000..7ecbfa5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/formatting.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013 Igalia, S.L." +__license__ = "LGPL" + +# If we were to adhere to the line-length requirements of 100 characters, +# this file would be even more cumbersome to look at than it already is. +# We shall respect the line-length requirements for all files that are not +# formatting.py. +# ruff: noqa: E501 + +import copy +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.formatting +import cthulhu.settings + +formatting = { + 'speech': { + Atspi.Role.MENU_ITEM: { + 'focused': 'expandableState', + 'unfocused': 'labelAndName + pause + unrelatedLabels + pause + menuItemCheckedState + expandableState + availability + ' + cthulhu.formatting.MNEMONIC + ' + accelerator + pause + positionInList', + 'basicWhereAmI': 'ancestors + pause + labelAndName + pause + unrelatedLabels + pause + accelerator + pause + positionInList + ' + cthulhu.formatting.MNEMONIC + }, + }, + 'braille': { + Atspi.Role.MENU_ITEM: { + 'unfocused': '[Component(obj,\ + asString(label + (displayedText or unrelatedLabels) + expandableState + availability) + asString(accelerator),\ + indicator=asString(menuItemCheckedState))]' + }, + } +} + +class Formatting(cthulhu.formatting.Formatting): + def __init__(self, script): + cthulhu.formatting.Formatting.__init__(self, script) + self.update(copy.deepcopy(formatting)) + self._defaultFormatting = cthulhu.formatting.Formatting(script) + + def getFormat(self, **args): + if args.get('useDefaultFormatting', False): + return self._defaultFormatting.getFormat(**args) + else: + return cthulhu.formatting.Formatting.getFormat(self, **args) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script.py new file mode 100644 index 0000000..578c30e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010-2013 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.toolkits.clutter as clutter +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .formatting import Formatting +from .script_utilities import Utilities + +class Script(clutter.Script): + + def __init__(self, app): + clutter.Script.__init__(self, app) + + def getFormatting(self): + """Returns the formatting strings for this script.""" + return Formatting(self) + + def getUtilities(self): + return Utilities(self) + + def deactivate(self): + """Called when this script is deactivated.""" + + self.utilities.clearCachedObjects() + super().deactivate() + + def skipObjectEvent(self, event): + """Determines whether or not this event should be skipped due to + being redundant, part of an event flood, etc.""" + + if AXUtilities.is_window(event.source): + return self.utilities.isBogusWindowFocusClaim(event) + + return clutter.Script.skipObjectEvent(self, event) + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + if event is not None and event.type == "window:activate" \ + and newFocus is not None and not AXObject.get_name(newFocus): + queuedEvent = self._getQueuedEvent("object:state-changed:focused", True) + if queuedEvent and queuedEvent.source != event.source: + msg = "GNOME SHELL: Have matching focused event. Not announcing nameless window." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().locusOfFocusChanged(event, oldFocus, newFocus) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if not AXUtilities.is_label(event.source): + clutter.Script.onNameChanged(self, event) + return + + # If we're already in a dialog, and a label inside that dialog changes its name, + # present the new name. Example: the "Command not found" label in the Run dialog. + dialog = AXObject.find_ancestor(cthulhu_state.locusOfFocus, AXUtilities.is_dialog) + tokens = ["GNOME SHELL: focus", cthulhu_state.locusOfFocus, "is in dialog:", dialog] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if dialog and AXObject.is_ancestor(event.source, dialog): + msg = "GNOME SHELL: Label changed name in current dialog. Presenting." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.presentMessage(AXObject.get_name(event.source)) + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + # Some buttons, like the Wikipedia button, claim to be selected but + # lack STATE_SELECTED. The other buttons, such as in the Dash and + # event switcher, seem to have the right state. Since the ones with + # the wrong state seem to be things we don't want to present anyway + # we'll stop doing so and hope we are right. + if event.detail1: + if AXUtilities.is_panel(event.source): + AXObject.clear_cache(event.source) + if AXUtilities.is_selected(event.source): + cthulhu.setLocusOfFocus(event, event.source) + return + + clutter.Script.onSelectedChanged(self, event) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + return + + # We're getting a spurious focus claim from the gnome-shell window after + # the window switcher is used. + if AXUtilities.is_window(event.source): + return + + if not AXObject.get_name(event.source) and AXUtilities.is_menu_item(event.source) \ + and not self.utilities.labelsForObject(event.source): + descendant = AXObject.find_descendant(event.source, AXUtilities.is_slider) + if descendant is not None: + cthulhu.setLocusOfFocus(event, descendant) + return + + clutter.Script.onFocusedChanged(self, event) + + def echoPreviousWord(self, obj, offset=None): + try: + text = obj.queryText() + except NotImplementedError: + return False + + if not offset: + if text.caretOffset == -1: + offset = text.characterCount - 1 + else: + offset = text.caretOffset - 1 + + if offset == 0: + return False + + return super().echoPreviousWord(obj, offset) + + def isActivatableEvent(self, event): + if event.type.startswith('object:state-changed:selected') and event.detail1: + return True + + if self.utilities.isBogusWindowFocusClaim(event): + return False + + return super().isActivatableEvent(event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script_utilities.py new file mode 100644 index 0000000..091151f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/gnome-shell/script_utilities.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities +from cthulhu.ax_object import AXObject +from cthulhu.ax_selection import AXSelection +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + script_utilities.Utilities.__init__(self, script) + self._isLayoutOnly = {} + + def clearCachedObjects(self): + self._isLayoutOnly = {} + + def selectedChildren(self, obj): + if AXObject.supports_selection(obj): + return AXSelection.get_selected_children(obj) + + # This is a workaround for bgo#738705. + if not AXUtilities.is_panel(obj): + return [] + + return AXUtilities.find_all_selected_objects(obj) + + def insertedText(self, event): + if event.any_data: + return event.any_data + + if event.detail1 == -1: + msg = "GNOME SHELL: Broken text insertion event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + text = self.queryNonEmptyText(event.source) + if text: + string = text.getText(0, -1) + if string: + msg = f"GNOME SHELL: Returning last char in '{string}'" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return string[-1] + + msg = "GNOME SHELL: Unable to correct broken text insertion event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + return "" + + def selectedText(self, obj): + string, start, end = super().selectedText(obj) + if -1 not in [start, end]: + return string, start, end + + tokens = [f"GNOME SHELL: Bogus selection range ({start}, {end}) for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + text = self.queryNonEmptyText(obj) + if text.getNSelections() > 0: + string = text.getText(0, -1) + start, end = 0, len(string) + + tokens = [f"GNOME SHELL: Returning '{string}' ({start}, {end}) for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return string, start, end + + def unrelatedLabels(self, root, onlyShowing=True, minimumWords=3): + if not root: + return [] + + def hasRole(x): + return AXUtilities.is_dialog(x) \ + or AXUtilities.is_notification(x) \ + or AXUtilities.is_menu_item(x) + + if not hasRole(root) and AXObject.find_ancestor(root, hasRole) is None: + tokens = ["GNOME SHELL: Not seeking unrelated labels for", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + return super().unrelatedLabels(root, onlyShowing, minimumWords) + + def isLayoutOnly(self, obj): + rv = self._isLayoutOnly.get(hash(obj)) + if rv is not None: + return rv + + rv = super().isLayoutOnly(obj) + if not rv and AXUtilities.is_panel(obj) and AXObject.get_child_count(obj) == 1: + child = AXObject.get_child(obj, 0) + if self.displayedLabel(obj) == AXObject.get_name(child) \ + and not AXUtilities.is_label(child): + rv = True + tokens = ["GNOME SHELL:", obj, "is deemed to be layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._isLayoutOnly[hash(obj)] = rv + return rv + + + def isBogusWindowFocusClaim(self, event): + if event.type.startswith('object:state-changed:focused') and event.detail1 \ + and AXUtilities.is_window(event.source) \ + and not self.canBeActiveWindow(event.source): + msg = "GNOME SHELL: Event is believed to be bogus window focus claim" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/__init__.py new file mode 100644 index 0000000..470f7b8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for kwin.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script.py new file mode 100644 index 0000000..f26e7bf --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for kwin.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2019 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu.scripts import switcher +from cthulhu.scripts.toolkits import Qt + +from .script_utilities import Utilities + + +class Script(switcher.Script, Qt.Script): + + def __init__(self, app): + """Creates a new script for the given application.""" + + super().__init__(app) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script_utilities.py new file mode 100644 index 0000000..a87d152 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/kwin/script_utilities.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2019 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities +from cthulhu.scripts import switcher + + +class Utilities(switcher.Utilities): + + def __init__(self, script): + super().__init__(script) + + def isSwitcherContainer(self, obj): + """Returns True if obj is the switcher container.""" + + return AXUtilities.is_filler(obj) and AXUtilities.is_focused(obj) + + def isSwitcherSelectionChangeEventType(self, event): + """Returns True if this event is the one we use to present changes.""" + + if event.type.startswith("object:state-changed:focused"): + return event.detail1 + + return False + + def getSelectionName(self, container): + """Returns the name of the currently-selected item.""" + + if self.isSwitcherContainer(container): + return AXObject.get_name(container) + + return "" diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/__init__.py new file mode 100644 index 0000000..e782ac8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" Custom script for notification daemon.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/script.py new file mode 100644 index 0000000..41eeebe --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notification-daemon/script.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" Custom script for The notification daemon.""" + +__id__ = "" +__version__ = "" +__date__ = "" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import cthulhu.messages as messages +import cthulhu.scripts.default as default +import cthulhu.settings as settings +from cthulhu.ax_utilities import AXUtilities + + +######################################################################## +# # +# The notification-daemon script class. # +# # +######################################################################## + +class Script(default.Script): + + def onWindowCreated(self, event): + """Callback for window:create accessibility events.""" + + allLabels = AXUtilities.find_all_labels(event.source) + texts = [self.utilities.displayedText(acc) for acc in allLabels] + text = f"{messages.NOTIFICATION} {' '.join(texts)}" + + voice = self.speechGenerator.voice(obj=event.source, string=text) + self.speakMessage(text, voice=voice) + self.displayBrailleMessage(text, flashTime=settings.brailleFlashTime) + self.notificationPresenter.save_notification(text) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/__init__.py new file mode 100644 index 0000000..b8d617c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" Custom script for The notify-osd""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/script.py new file mode 100644 index 0000000..b541bb4 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/notify-osd/script.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +""" Custom script for The notify-osd""" + +__id__ = "" +__version__ = "" +__date__ = "" +__copyright__ = "Copyright (c) 2009 Eitan Isaacson" +__license__ = "LGPL" + +import cthulhu.messages as messages +import cthulhu.scripts.default as default +import cthulhu.settings as settings +import cthulhu.settings_manager as settings_manager +from cthulhu.ax_object import AXObject + +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# The notify-osd script class. # +# # +######################################################################## + +class Script(default.Script): + def onValueChanged(self, event): + try: + ivalue = event.source.queryValue() + value = int(ivalue.currentValue) + except NotImplementedError: + value = -1 + + if value >= 0: + string = str(value) + voice = self.speechGenerator.voice(obj=event.source, string=string) + self.speakMessage(string, voice=voice) + self.displayBrailleMessage(string, + flashTime=settings.brailleFlashTime) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + try: + ivalue = event.source.queryValue() + value = ivalue.currentValue + except NotImplementedError: + value = -1 + + message = "" + if value < 0: + self.speakMessage(messages.NOTIFICATION) + message = '%s %s' % (AXObject.get_name(event.source), + AXObject.get_description(event.source)) + else: + # A gauge notification, e.g. the Ubuntu volume notification that + # appears when you press the multimedia keys. + # + message = '%s %d' % (AXObject.get_name(event.source), value) + self.speakMessage(message) + + voice = self.speechGenerator.voice(obj=event.source, string=message) + self.speakMessage(message, voice=voice) + self.displayBrailleMessage(message, flashTime=settings.brailleFlashTime) + self.notificationPresenter.save_notification(message) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/chat.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/chat.py new file mode 100644 index 0000000..c7cfc39 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/chat.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom chat module for Pidgin.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import cthulhu.chat as chat + +######################################################################## +# # +# The Pidgin chat class. # +# # +######################################################################## + +class Chat(chat.Chat): + + def __init__(self, script, buddyListAncestries): + + chat.Chat.__init__(self, script, buddyListAncestries) + + def isTypingStatusChangedEvent(self, event): + """Returns True if event is associated with a change in typing status. + + Arguments: + - event: the accessible event being examined + """ + + if not event.type.startswith("object:text-changed:insert"): + return False + + # Bit of a hack. Pidgin inserts text into the chat history when the + # user is typing. We seem able to (more or less) reliably distinguish + # this text via its attributes because these attributes are absent + # from user inserted text -- no matter how that text is formatted. + # + attr, start, end = \ + self._script.utilities.textAttributes(event.source, event.detail1) + + if float(attr.get('scale', '1')) < 1 \ + or int(attr.get('weight', '400')) < 400: + return True + + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script.py new file mode 100644 index 0000000..3f65fd5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for pidgin.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.debug as debug +import cthulhu.messages as messages +import cthulhu.scripts.toolkits.GAIL as GAIL +import cthulhu.settings as settings +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .chat import Chat +from .script_utilities import Utilities +from .speech_generator import SpeechGenerator + +######################################################################## +# # +# The Pidgin script class. # +# # +######################################################################## + +class Script(GAIL.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + # So we can take an educated guess at identifying the buddy list. + # + self._buddyListAncestries = [[Atspi.Role.TREE_TABLE, + Atspi.Role.SCROLL_PANE, + Atspi.Role.FILLER, + Atspi.Role.PAGE_TAB, + Atspi.Role.PAGE_TAB_LIST, + Atspi.Role.FILLER, + Atspi.Role.FRAME]] + + GAIL.Script.__init__(self, app) + + def getChat(self): + """Returns the 'chat' class for this script.""" + + return Chat(self, self._buddyListAncestries) + + def getSpeechGenerator(self): + """Returns the speech generator for this script. """ + + return SpeechGenerator(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings. Here we need to add the + handlers for chat functionality. + """ + + GAIL.Script.setupInputEventHandlers(self) + self.inputEventHandlers.update(self.chat.inputEventHandlers) + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + return self.chat.keyBindings + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application. The chat-related options get + created by the chat module.""" + + return self.chat.getAppPreferencesGUI() + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return self.chat.getPreferencesFromGUI() + + def onChildrenAdded(self, event): + """Callback for object:children-changed:add accessibility events.""" + + AXObject.clear_cache_now("children-changed event.") + + # Check to see if a new chat room tab has been created and if it + # has, then announce its name. See bug #469098 for more details. + # + if event.type.startswith("object:children-changed:add"): + rolesList = [Atspi.Role.PAGE_TAB_LIST, + Atspi.Role.FILLER, + Atspi.Role.FRAME] + if self.utilities.hasMatchingHierarchy(event.source, rolesList): + # As it's possible to get this component hierarchy in other + # places than the chat room (i.e. the Preferences dialog), + # we check to see if the name of the frame is the same as one + # of its children. If it is, then it's a chat room tab event. + # For a final check, we only announce the new chat tab if the + # last child has a name. + # + nameFound = False + frame = AXObject.find_ancestor(event.source, + lambda x: AXObject.get_role(x) == Atspi.Role.FRAME) + frameName = AXObject.get_name(frame) + if not frameName: + return + for child in AXObject.iter_children(event.source): + if frameName == AXObject.get_name(child): + nameFound = True + break + if nameFound: + child = AXObject.get_child(event.source, -1) + childName = AXObject.get_name(child) + if childName: + line = messages.CHAT_NEW_TAB % childName + voice = self.speechGenerator.voice(obj=child, string=line) + self.speakMessage(line, voice=voice) + + def onNameChanged(self, event): + """Called whenever a property on an object changes. + + Arguments: + - event: the Event + """ + + if self.chat.isInBuddyList(event.source): + return + else: + GAIL.Script.onNameChanged(self, event) + + def onTextDeleted(self, event): + """Called whenever text is deleted from an object. + + Arguments: + - event: the Event + """ + + if self.chat.isInBuddyList(event.source): + return + else: + GAIL.Script.onTextDeleted(self, event) + + def onTextInserted(self, event): + """Called whenever text is added to an object.""" + + if self.chat.presentInsertedText(event): + return + + GAIL.Script.onTextInserted(self, event) + + def onValueChanged(self, event): + """Called whenever an object's value changes. Currently, the + value changes for non-focused objects are ignored. + + Arguments: + - event: the Event + """ + + if self.chat.isInBuddyList(event.source): + return + else: + GAIL.Script.onValueChanged(self, event) + + def onWindowActivated(self, event): + """Called whenever a toplevel window is activated.""" + + if not settings.enableSadPidginHack: + msg = "PIDGIN: Hack for missing events disabled" + debug.printMessage(debug.LEVEL_INFO, msg, True) + GAIL.Script.onWindowActivated(self, event) + return + + msg = "PIDGIN: Starting hack for missing events" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # Hack to "tickle" the accessible hierarchy. Otherwise, the + # events we need to present text added to the chatroom are + # missing. + AXUtilities.find_all_page_tabs(event.source) + + msg = "PIDGIN: Hack to work around missing events complete" + debug.printMessage(debug.LEVEL_INFO, msg, True) + GAIL.Script.onWindowActivated(self, event) + + def onExpandedChanged(self, event): + """Callback for object:state-changed:expanded accessibility events.""" + + # Overridden here because the event.source is in a hidden column. + obj = event.source + if self.chat.isInBuddyList(obj): + obj = AXObject.get_next_sibling(obj) + self.presentObject(obj, alreadyFocused=True) + return + + GAIL.Script.onExpandedChanged(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script_utilities.py new file mode 100644 index 0000000..eb3349c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/script_utilities.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Commonly-required utility methods needed by -- and potentially + customized by -- application and toolkit scripts. They have + been pulled out from the scripts because certain scripts had + gotten way too large as a result of including these methods.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +############################################################################# +# # +# Utilities # +# # +############################################################################# + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + """Creates an instance of the Utilities class. + + Arguments: + - script: the script with which this instance is associated. + """ + + script_utilities.Utilities.__init__(self, script) + + ######################################################################### + # # + # Utilities for finding, identifying, and comparing accessibles # + # # + ######################################################################### + + def childNodes(self, obj): + """Gets all of the children that have RELATION_NODE_CHILD_OF pointing + to this expanded table cell. Overridden here because the object + which contains the relation is in a hidden column and thus doesn't + have a column number (necessary for using getAccessibleAt()). + + Arguments: + -obj: the Accessible Object + + Returns: a list of all the child nodes + """ + + if not self._script.chat.isInBuddyList(obj): + return script_utilities.Utilities.childNodes(self, obj) + + parent = AXObject.get_parent(obj) + try: + table = parent.queryTable() + except Exception: + return [] + else: + if not AXUtilities.is_expanded(obj): + return [] + + nodes = [] + index = self.cellIndex(obj) + row = table.getRowAtIndex(index) + col = table.getColumnAtIndex(index + 1) + nodeLevel = self.nodeLevel(obj) + + # Candidates will be in the rows beneath the current row. + # Only check in the current column and stop checking as + # soon as the node level of a candidate is equal or less + # than our current level. + # + for i in range(row+1, table.nRows): + cell = table.getAccessibleAt(i, col) + nodeCell = AXObject.get_previous_sibling(cell) + relation = AXObject.get_relation(nodeCell, Atspi.RelationType.NODE_CHILD_OF) + if not relation: + continue + + nodeOf = relation.getTarget(0) + if self.isSameObject(obj, nodeOf): + nodes.append(cell) + elif self.nodeLevel(nodeOf) <= nodeLevel: + break + + return nodes + + def nodeLevel(self, obj): + """Determines the node level of this object if it is in a tree + relation, with 0 being the top level node. If this object is + not in a tree relation, then -1 will be returned. Overridden + here because the accessible we need is in a hidden column. + + Arguments: + -obj: the Accessible object + """ + + if not obj: + return -1 + + if not self._script.chat.isInBuddyList(obj): + return script_utilities.Utilities.nodeLevel(self, obj) + + obj = AXObject.get_previous_sibling(obj) + parent = AXObject.get_parent(obj) + try: + parent.queryTable() + except Exception: + return -1 + + nodes = [] + node = obj + done = False + while not done: + relation = AXObject.get_relation(node, Atspi.RelationType.NODE_CHILD_OF) + node = None + if relation: + node = relation.get_target(0) + + # We want to avoid situations where something gives us an + # infinite cycle of nodes. Bon Echo has been seen to do + # this (see bug 351847). + # + if (len(nodes) > 100) or nodes.count(node): + debug.printMessage(debug.LEVEL_WARNING, "PIDGIN: Detected a cycle of nodes") + done = True + elif node: + nodes.append(node) + else: + done = True + + return len(nodes) - 1 + + ######################################################################### + # # + # Utilities for working with the accessible text interface # + # # + ######################################################################### + + + + ######################################################################### + # # + # Miscellaneous Utilities # + # # + ######################################################################### + + def isZombie(self, obj): + if not super().isZombie(obj): + return False + + if AXObject.get_role(obj) != Atspi.Role.TOGGLE_BUTTON: + return True + + tokens = ["PIDGIN: Hacking around broken index in parent for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return AXObject.get_index_in_parent(obj) != -1 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/speech_generator.py new file mode 100644 index 0000000..80ebe1a --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/pidgin/speech_generator.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import cthulhu.speech_generator as speech_generator +from cthulhu.ax_object import AXObject + +######################################################################## +# # +# Custom SpeechGenerator # +# # +######################################################################## + +class SpeechGenerator(speech_generator.SpeechGenerator): + """Overrides _generateExpandableState so that we can provide access + to the expanded/collapsed state and node count for the buddy list. + """ + + def __init__(self, script): + speech_generator.SpeechGenerator.__init__(self, script) + + def _generateExpandableState(self, obj, **args): + result = [] + if self._script.chat.isInBuddyList(obj): + # The Pidgin buddy list consists of two columns. The + # column which is set as the expander column and which + # also contains the node relationship is hidden. Hidden + # columns are not included among a table's columns. The + # hidden object of interest seems to always immediately + # precede the visible object. + # + expanderCell = AXObject.get_previous_sibling(obj) + if expanderCell: + result.extend( + speech_generator.SpeechGenerator._generateExpandableState( + self, expanderCell, **args)) + else: + result.extend( + speech_generator.SpeechGenerator._generateExpandableState( + self, obj, **args)) + else: + result.extend( + speech_generator.SpeechGenerator._generateExpandableState( + self, obj, **args)) + return result + + def _generateNumberOfChildren(self, obj, **args): + result = [] + if self._script.chat.isInBuddyList(obj): + # The Pidgin buddy list consists of two columns. The + # column which is set as the expander column and which + # also contains the node relationship is hidden. Hidden + # columns are not included among a table's columns. The + # hidden object of interest seems to always immediately + # precede the visible object. + # + expanderCell = AXObject.get_previous_sibling(obj) + if expanderCell: + result.extend( + speech_generator.SpeechGenerator._generateNumberOfChildren( + self, expanderCell, **args)) + else: + result.extend( + speech_generator.SpeechGenerator._generateNumberOfChildren( + self, obj, **args)) + else: + result.extend( + speech_generator.SpeechGenerator._generateNumberOfChildren( + self, obj, **args)) + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/chat.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/chat.py new file mode 100644 index 0000000..bbfeaaf --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/chat.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom chat module for Smuxi.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2018 Igalia, S.L." +__license__ = "LGPL" + + +import cthulhu.chat as chat +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Chat(chat.Chat): + + def __init__(self, script, buddyListAncestries): + super().__init__(script, buddyListAncestries) + + def isFocusedChat(self, obj): + """Returns True if we plan to treat this chat as focused.""" + + pageTab = AXObject.find_ancestor(obj, AXUtilities.is_page_tab) + if pageTab is None: + return super().isFocusedChat(obj) + + return AXUtilities.is_showing(pageTab) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/script.py new file mode 100644 index 0000000..edfb179 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/smuxi-frontend-gnome/script.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Smuxi.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2018 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.scripts.toolkits.GAIL as GAIL +from .chat import Chat + +class Script(GAIL.Script): + + def __init__(self, app): + """Creates a new script for the given application.""" + + # So we can take an educated guess at identifying the buddy list. + self._buddyListAncestries = [[Atspi.Role.TREE_TABLE, + Atspi.Role.SCROLL_PANE, + Atspi.Role.SPLIT_PANE, + Atspi.Role.SPLIT_PANE, + Atspi.Role.FILLER, + Atspi.Role.FRAME]] + + super().__init__(app) + + def getChat(self): + """Returns the 'chat' class for this script.""" + + return Chat(self, self._buddyListAncestries) + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script.""" + + super().setupInputEventHandlers() + self.inputEventHandlers.update(self.chat.inputEventHandlers) + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + return self.chat.keyBindings + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration.""" + + return self.chat.getAppPreferencesGUI() + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return self.chat.getPreferencesFromGUI() + + def onTextInserted(self, event): + """Called whenever text is added to an object.""" + + if self.chat.presentInsertedText(event): + return + + super().onTextInserted(event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/braille_generator.py new file mode 100644 index 0000000..02c6a3c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/braille_generator.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for StarOffice and OpenOffice.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.braille as braille +import cthulhu.braille_generator as braille_generator +import cthulhu.object_properties as object_properties +import cthulhu.settings_manager as settings_manager +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +class BrailleGenerator(braille_generator.BrailleGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateRoleName(self, obj, **args): + if self._script.utilities.isDocument(obj): + return [] + + if self._script.utilities.isFocusableLabel(obj): + return [] + + return super()._generateRoleName(obj, **args) + + def _generateRowHeader(self, obj, **args): + """Returns an array of strings that represent the row header for an + object that is in a table, if it exists. Otherwise, an empty + array is returned. Overridden here so that we can get the + dynamic row header(s). + """ + + newOnly = args.get('newOnly', False) + rowHeader, columnHeader = \ + self._script.utilities.getDynamicHeadersForCell(obj, newOnly) + if not rowHeader: + return [] + + text = self._script.utilities.displayedText(rowHeader) + if text: + return [text] + + return [] + + def _generateColumnHeader(self, obj, **args): + """Returns an array of strings that represent the column header for an + object that is in a table, if it exists. Otherwise, an empty + array is returned. Overridden here so that we can get the + dynamic column header(s). + """ + + newOnly = args.get('newOnly', False) + rowHeader, columnHeader = \ + self._script.utilities.getDynamicHeadersForCell(obj, newOnly) + if not columnHeader: + return [] + + text = self._script.utilities.displayedText(columnHeader) + if text: + return [text] + + return [] + + def _generateRealTableCell(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateRealTableCell(obj, **args) + + if not AXObject.get_child_count(obj): + result = super()._generateRealTableCell(obj, **args) + else: + result = [] + formatType = args.get('formatType') + args['formatType'] = 'focused' + for child in AXObject.iter_children(obj): + result.extend(self.generate(child, **args)) + args['formatType'] = formatType + + if not self._script.utilities.isSpreadSheetCell(obj): + return result + + try: + objectText = self._script.utilities.substring(obj, 0, -1) + cellName = self._script.utilities.spreadSheetCellName(obj) + except Exception: + return [] + + return [braille.Component(obj, " ".join((objectText, cellName)))] + + def _generateTableCellDelimiter(self, obj, **args): + return braille.Region(object_properties.TABLE_CELL_DELIMITER_BRAILLE) + + def _generateTableCellRow(self, obj, **args): + if not self._script.utilities.shouldReadFullRow(obj): + return self._generateRealTableCell(obj, **args) + + if not self._script.utilities.isSpreadSheetCell(obj): + return super()._generateTableCellRow(obj, **args) + + cells = self._script.utilities.getShowingCellsInSameRow(obj) + if not cells: + return [] + + result = [] + for cell in cells: + cellResult = self._generateRealTableCell(cell, **args) + if cellResult and result: + result.append(self._generateTableCellDelimiter(obj, **args)) + result.extend(cellResult) + + return result + + def _generateChildTab(self, obj, **args): + """If we are in the slide presentation scroll pane, also announce the + current page tab. See bug #538056 for more details. + """ + result = [] + rolesList = [Atspi.Role.SCROLL_PANE, \ + Atspi.Role.PANEL, \ + Atspi.Role.PANEL, \ + Atspi.Role.ROOT_PANE, \ + Atspi.Role.FRAME, \ + Atspi.Role.APPLICATION] + if self._script.utilities.hasMatchingHierarchy(obj, rolesList): + parent = AXObject.get_parent(obj) + for child in AXObject.iter_children(parent, AXUtilities.is_page_tab_list): + for tab in AXObject.iter_children(child, AXUtilities.is_selected): + args['role'] = AXObject.get_role(tab) + result.extend(self.generate(tab, **args)) + return result + + def _generateAncestors(self, obj, **args): + if self._script._lastCommandWasStructNav: + return [] + + return super()._generateAncestors(obj, **args) + + def _generateIncludeContext(self, obj, **args): + if self._script._lastCommandWasStructNav: + return False + + return super()._generateIncludeContext(obj, **args) + + def generateBraille(self, obj, **args): + args['useDefaultFormatting'] = self._script.utilities.isNonFocusableList(obj) + oldRole = self._overrideRole(self._getAlternativeRole(obj, **args), args) + + result = super().generateBraille(obj, **args) + + del args['useDefaultFormatting'] + self._restoreRole(oldRole, args) + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/formatting.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/formatting.py new file mode 100644 index 0000000..985bf47 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/formatting.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom formatting for OpenOffice and StarOffice.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +# If we were to adhere to the line-length requirements of 100 characters, +# this file would be even more cumbersome to look at than it already is. +# We shall respect the line-length requirements for all files that are not +# formatting.py. +# ruff: noqa: E501 + +import copy +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.formatting +import cthulhu.settings + +formatting = { + 'speech': { + Atspi.Role.TABLE_CELL: { + 'focused': 'endOfTableIndicator + pause + tableCellRow + pause', + 'unfocused': 'endOfTableIndicator + pause + tableCellRow + pause', + 'basicWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + expandableState + pause + nodeLevel + pause', + 'detailedWhereAmI': 'parentRoleName + pause + columnHeader + pause + rowHeader + pause + roleName + pause + cellCheckedState + pause + (realActiveDescendantDisplayedText or imageDescription + image) + pause + columnAndRow + pause + tableCellRow + pause + expandableState + pause + nodeLevel + pause' + }, + 'REAL_ROLE_TABLE_CELL': { + 'focused': 'newRowHeader + newColumnHeader + realActiveDescendantDisplayedText', + 'unfocused': 'newRowHeader + newColumnHeader + realActiveDescendantDisplayedText', + }, + 'ROLE_SPREADSHEET_CELL': { + # We treat spreadsheet cells differently from other table cells in + # whereAmI. + # + 'basicWhereAmI': 'roleName + pause + column + pause + columnHeader + pause + row + pause + rowHeader + pause + (textContent or realTableCell) + pause + anyTextSelection + pause' + }, + }, + 'braille': { + Atspi.Role.LIST: { + 'unfocused': '[Component(obj,\ + asString(labelOrName + roleName + required))]' + }, + Atspi.Role.SCROLL_PANE: { + 'unfocused': 'asPageTabOrScrollPane\ + + (childTab\ + and ([Region(" ")] + childTab) or [])' + } + } +} + +class Formatting(cthulhu.formatting.Formatting): + def __init__(self, script): + cthulhu.formatting.Formatting.__init__(self, script) + self.update(copy.deepcopy(formatting)) + self._defaultFormatting = cthulhu.formatting.Formatting(script) + + def getFormat(self, **args): + if args.get('useDefaultFormatting', False): + return self._defaultFormatting.getFormat(**args) + else: + return cthulhu.formatting.Formatting.getFormat(self, **args) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script.py new file mode 100644 index 0000000..5266eb5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script.py @@ -0,0 +1,996 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for LibreOffice.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +from gi.repository import Gtk + +import cthulhu.cmdnames as cmdnames +import cthulhu.debug as debug +import cthulhu.scripts.default as default +import cthulhu.guilabels as guilabels +import cthulhu.keybindings as keybindings +import cthulhu.input_event as input_event +import cthulhu.messages as messages +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.settings_manager as settings_manager +import cthulhu.structural_navigation as structural_navigation +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .braille_generator import BrailleGenerator +from .formatting import Formatting +from .script_utilities import Utilities +from .spellcheck import SpellCheck +from .speech_generator import SpeechGenerator + +_settingsManager = settings_manager.getManager() + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + default.Script.__init__(self, app) + + self.speakSpreadsheetCoordinatesCheckButton = None + self.alwaysSpeakSelectedSpreadsheetRangeCheckButton = None + self.skipBlankCellsCheckButton = None + self.speakCellCoordinatesCheckButton = None + self.speakCellHeadersCheckButton = None + self.speakCellSpanCheckButton = None + + # The spreadsheet input line. + # + self.inputLineForCell = None + + # Dictionaries for the calc and writer dynamic row and column headers. + # + self.dynamicColumnHeaders = {} + self.dynamicRowHeaders = {} + + def getBrailleGenerator(self): + """Returns the braille generator for this script. + """ + return BrailleGenerator(self) + + def getSpeechGenerator(self): + """Returns the speech generator for this script. + """ + return SpeechGenerator(self) + + def getSpellCheck(self): + """Returns the spellcheck for this script.""" + + return SpellCheck(self) + + def getFormatting(self): + """Returns the formatting strings for this script.""" + return Formatting(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def getStructuralNavigation(self): + """Returns the 'structural navigation' class for this script. + """ + types = self.getEnabledStructuralNavigationTypes() + return structural_navigation.StructuralNavigation(self, types, enabled=False) + + def getEnabledStructuralNavigationTypes(self): + """Returns a list of the structural navigation object types + enabled in this script. + """ + + enabledTypes = [structural_navigation.StructuralNavigation.TABLE_CELL] + + return enabledTypes + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings. In this particular case, + we just want to be able to add a handler to return the contents of + the input line. + """ + + default.Script.setupInputEventHandlers(self) + self.inputEventHandlers.update( + self.structuralNavigation.inputEventHandlers) + + self.inputEventHandlers["presentInputLineHandler"] = \ + input_event.InputEventHandler( + Script.presentInputLine, + cmdnames.PRESENT_INPUT_LINE) + + self.inputEventHandlers["setDynamicColumnHeadersHandler"] = \ + input_event.InputEventHandler( + Script.setDynamicColumnHeaders, + cmdnames.DYNAMIC_COLUMN_HEADER_SET) + + self.inputEventHandlers["clearDynamicColumnHeadersHandler"] = \ + input_event.InputEventHandler( + Script.clearDynamicColumnHeaders, + cmdnames.DYNAMIC_COLUMN_HEADER_CLEAR) + + self.inputEventHandlers["setDynamicRowHeadersHandler"] = \ + input_event.InputEventHandler( + Script.setDynamicRowHeaders, + cmdnames.DYNAMIC_ROW_HEADER_SET) + + self.inputEventHandlers["clearDynamicRowHeadersHandler"] = \ + input_event.InputEventHandler( + Script.clearDynamicRowHeaders, + cmdnames.DYNAMIC_ROW_HEADER_CLEAR) + + self.inputEventHandlers["panBrailleLeftHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleLeft, + cmdnames.PAN_BRAILLE_LEFT, + False) # Do not enable learn mode for this action + + self.inputEventHandlers["panBrailleRightHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleRight, + cmdnames.PAN_BRAILLE_RIGHT, + False) # Do not enable learn mode for this action + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + keyBindings = keybindings.KeyBindings() + + keyBindings.add( + keybindings.KeyBinding( + "a", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["presentInputLineHandler"])) + + keyBindings.add( + keybindings.KeyBinding( + "r", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["setDynamicColumnHeadersHandler"], + 1)) + + keyBindings.add( + keybindings.KeyBinding( + "r", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["clearDynamicColumnHeadersHandler"], + 2)) + + keyBindings.add( + keybindings.KeyBinding( + "c", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["setDynamicRowHeadersHandler"], + 1)) + + keyBindings.add( + keybindings.KeyBinding( + "c", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["clearDynamicRowHeadersHandler"], + 2)) + + bindings = self.structuralNavigation.keyBindings + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + return keyBindings + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application.""" + + grid = Gtk.Grid() + grid.set_border_width(12) + + label = guilabels.SPREADSHEET_SPEAK_CELL_COORDINATES + value = _settingsManager.getSetting('speakSpreadsheetCoordinates') + self.speakSpreadsheetCoordinatesCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.speakSpreadsheetCoordinatesCheckButton.set_active(value) + grid.attach(self.speakSpreadsheetCoordinatesCheckButton, 0, 0, 1, 1) + + label = guilabels.SPREADSHEET_SPEAK_SELECTED_RANGE + value = _settingsManager.getSetting('alwaysSpeakSelectedSpreadsheetRange') + self.alwaysSpeakSelectedSpreadsheetRangeCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.alwaysSpeakSelectedSpreadsheetRangeCheckButton.set_active(value) + grid.attach(self.alwaysSpeakSelectedSpreadsheetRangeCheckButton, 0, 1, 1, 1) + + tableFrame = Gtk.Frame() + grid.attach(tableFrame, 0, 2, 1, 1) + + label = Gtk.Label(label=f"{guilabels.TABLE_NAVIGATION}") + label.set_use_markup(True) + tableFrame.set_label_widget(label) + + tableAlignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) + tableAlignment.set_padding(0, 0, 12, 0) + tableFrame.add(tableAlignment) + tableGrid = Gtk.Grid() + tableAlignment.add(tableGrid) + + label = guilabels.TABLE_SPEAK_CELL_COORDINATES + value = _settingsManager.getSetting('speakCellCoordinates') + self.speakCellCoordinatesCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.speakCellCoordinatesCheckButton.set_active(value) + tableGrid.attach(self.speakCellCoordinatesCheckButton, 0, 0, 1, 1) + + label = guilabels.TABLE_SPEAK_CELL_SPANS + value = _settingsManager.getSetting('speakCellSpan') + self.speakCellSpanCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.speakCellSpanCheckButton.set_active(value) + tableGrid.attach(self.speakCellSpanCheckButton, 0, 1, 1, 1) + + label = guilabels.TABLE_ANNOUNCE_CELL_HEADER + value = _settingsManager.getSetting('speakCellHeaders') + self.speakCellHeadersCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.speakCellHeadersCheckButton.set_active(value) + tableGrid.attach(self.speakCellHeadersCheckButton, 0, 2, 1, 1) + + label = guilabels.TABLE_SKIP_BLANK_CELLS + value = _settingsManager.getSetting('skipBlankCells') + self.skipBlankCellsCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.skipBlankCellsCheckButton.set_active(value) + tableGrid.attach(self.skipBlankCellsCheckButton, 0, 3, 1, 1) + + spellcheck = self.spellcheck.getAppPreferencesGUI() + grid.attach(spellcheck, 0, len(grid.get_children()), 1, 1) + grid.show_all() + + return grid + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + prefs = { + 'speakCellSpan': + self.speakCellSpanCheckButton.get_active(), + 'speakCellHeaders': + self.speakCellHeadersCheckButton.get_active(), + 'skipBlankCells': + self.skipBlankCellsCheckButton.get_active(), + 'speakCellCoordinates': + self.speakCellCoordinatesCheckButton.get_active(), + 'speakSpreadsheetCoordinates': + self.speakSpreadsheetCoordinatesCheckButton.get_active(), + 'alwaysSpeakSelectedSpreadsheetRange': + self.alwaysSpeakSelectedSpreadsheetRangeCheckButton.get_active(), + } + + prefs.update(self.spellcheck.getPreferencesFromGUI()) + return prefs + + def panBrailleLeft(self, inputEvent=None, panAmount=0): + """In document content, we want to use the panning keys to browse the + entire document. + """ + + if self.flatReviewPresenter.is_active() \ + or not self.isBrailleBeginningShowing() \ + or self.utilities.isSpreadSheetCell(cthulhu_state.locusOfFocus) \ + or not self.utilities.isTextArea(cthulhu_state.locusOfFocus): + return default.Script.panBrailleLeft(self, inputEvent, panAmount) + + text = cthulhu_state.locusOfFocus.queryText() + string, startOffset, endOffset = text.getTextAtOffset( + text.caretOffset, Atspi.TextBoundaryType.LINE_START) + if 0 < startOffset: + text.setCaretOffset(startOffset-1) + return True + + obj = self.utilities.findPreviousObject(cthulhu_state.locusOfFocus) + try: + text = obj.queryText() + except Exception: + pass + else: + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + text.setCaretOffset(text.characterCount) + return True + + return default.Script.panBrailleLeft(self, inputEvent, panAmount) + + def panBrailleRight(self, inputEvent=None, panAmount=0): + """In document content, we want to use the panning keys to browse the + entire document. + """ + + if self.flatReviewPresenter.is_active() \ + or not self.isBrailleEndShowing() \ + or self.utilities.isSpreadSheetCell(cthulhu_state.locusOfFocus) \ + or not self.utilities.isTextArea(cthulhu_state.locusOfFocus): + return default.Script.panBrailleRight(self, inputEvent, panAmount) + + text = cthulhu_state.locusOfFocus.queryText() + string, startOffset, endOffset = text.getTextAtOffset( + text.caretOffset, Atspi.TextBoundaryType.LINE_START) + if endOffset < text.characterCount: + text.setCaretOffset(endOffset) + return True + + obj = self.utilities.findNextObject(cthulhu_state.locusOfFocus) + try: + text = obj.queryText() + except Exception: + pass + else: + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + text.setCaretOffset(0) + return True + + return default.Script.panBrailleRight(self, inputEvent, panAmount) + + def presentInputLine(self, inputEvent): + """Presents the contents of the spread sheet input line (assuming we + have a handle to it - generated when we first focus on a spread + sheet table cell. + + This will be either the contents of the table cell that has focus + or the formula associated with it. + + Arguments: + - inputEvent: if not None, the input event that caused this action. + """ + + if not self.utilities.isSpreadSheetCell(cthulhu_state.locusOfFocus): + return + + inputLine = self.utilities.locateInputLine(cthulhu_state.locusOfFocus) + if not inputLine: + return + + text = self.utilities.displayedText(inputLine) + if not text: + text = messages.EMPTY + + self.presentMessage(text) + + def setDynamicColumnHeaders(self, inputEvent): + """Set the row for the dynamic header columns to use when speaking + calc cell entries. In order to set the row, the user should first set + focus to the row that they wish to define and then press Insert-r. + + Once the user has defined the row, it will be used to first speak + this header when moving between columns. + + Arguments: + - inputEvent: if not None, the input event that caused this action. + """ + + cell = cthulhu_state.locusOfFocus + parent = AXObject.get_parent(cell) + if AXObject.get_role(parent) == Atspi.Role.TABLE_CELL: + cell = parent + + row, column, table = self.utilities.getRowColumnAndTable(cell) + if table: + self.dynamicColumnHeaders[hash(table)] = row + self.presentMessage(messages.DYNAMIC_COLUMN_HEADER_SET % (row+1)) + + return True + + def clearDynamicColumnHeaders(self, inputEvent): + """Clear the dynamic header column. + + Arguments: + - inputEvent: if not None, the input event that caused this action. + """ + + cell = cthulhu_state.locusOfFocus + parent = AXObject.get_parent(cell) + if AXObject.get_role(parent) == Atspi.Role.TABLE_CELL: + cell = parent + + row, column, table = self.utilities.getRowColumnAndTable(cell) + try: + del self.dynamicColumnHeaders[hash(table)] + self.presentationInterrupt() + self.presentMessage(messages.DYNAMIC_COLUMN_HEADER_CLEARED) + except Exception: + pass + + return True + + def setDynamicRowHeaders(self, inputEvent): + """Set the column for the dynamic header rows to use when speaking + calc cell entries. In order to set the column, the user should first + set focus to the column that they wish to define and then press + Insert-c. + + Once the user has defined the column, it will be used to first speak + this header when moving between rows. + + Arguments: + - inputEvent: if not None, the input event that caused this action. + """ + + cell = cthulhu_state.locusOfFocus + parent = AXObject.get_parent(cell) + if AXObject.get_role(parent) == Atspi.Role.TABLE_CELL: + cell = parent + + row, column, table = self.utilities.getRowColumnAndTable(cell) + if table: + self.dynamicRowHeaders[hash(table)] = column + self.presentMessage( + messages.DYNAMIC_ROW_HEADER_SET % self.utilities.columnConvert(column+1)) + + return True + + def clearDynamicRowHeaders(self, inputEvent): + """Clear the dynamic row headers. + + Arguments: + - inputEvent: if not None, the input event that caused this action. + """ + + cell = cthulhu_state.locusOfFocus + parent = AXObject.get_parent(cell) + if AXObject.get_role(parent) == Atspi.Role.TABLE_CELL: + cell = parent + + row, column, table = self.utilities.getRowColumnAndTable(cell) + try: + del self.dynamicRowHeaders[hash(table)] + self.presentationInterrupt() + self.presentMessage(messages.DYNAMIC_ROW_HEADER_CLEARED) + except Exception: + pass + + return True + + def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): + """Called when the visual object with focus changes. + + Arguments: + - event: if not None, the Event that caused the change + - oldLocusOfFocus: Accessible that is the old locus of focus + - newLocusOfFocus: Accessible that is the new locus of focus + """ + + # Check to see if this is this is for the find command. See + # comment #18 of bug #354463. + # + if self.findCommandRun and \ + event.type.startswith("object:state-changed:focused"): + self.findCommandRun = False + self.find() + return + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.quit() + + if self.spellcheck.isSuggestionsItem(newLocusOfFocus) \ + and not self.spellcheck.isSuggestionsItem(oldLocusOfFocus): + cthulhu.emitRegionChanged(newLocusOfFocus) + self.updateBraille(newLocusOfFocus) + self.spellcheck.presentSuggestionListItem(includeLabel=True) + return + + # TODO - JD: Sad hack that wouldn't be needed if LO were fixed. + # If we are in the slide presentation scroll pane, also announce + # the current page tab. See bug #538056 for more details. + # + rolesList = [Atspi.Role.SCROLL_PANE, + Atspi.Role.PANEL, + Atspi.Role.PANEL, + Atspi.Role.ROOT_PANE, + Atspi.Role.FRAME, + Atspi.Role.APPLICATION] + if self.utilities.hasMatchingHierarchy(newLocusOfFocus, rolesList): + parent = AXObject.get_parent(newLocusOfFocus) + for child in AXObject.iter_children(parent, AXUtilities.is_page_tab_list): + for tab in AXObject.iter_children(child, AXUtilities.is_selected): + self.presentObject(tab) + + # TODO - JD: This is a hack that needs to be done better. For now it + # fixes the broken echo previous word on Return. + elif newLocusOfFocus and oldLocusOfFocus \ + and AXObject.get_role(newLocusOfFocus) == Atspi.Role.PARAGRAPH \ + and AXObject.get_role(oldLocusOfFocus) == Atspi.Role.PARAGRAPH \ + and newLocusOfFocus != oldLocusOfFocus: + lastKey, mods = self.utilities.lastKeyAndModifiers() + if lastKey == "Return" and _settingsManager.getSetting('enableEchoByWord'): + self.echoPreviousWord(oldLocusOfFocus) + return + + # TODO - JD: And this hack is another one that needs to be done better. + # But this will get us to speak the entire paragraph when navigation by + # paragraph has occurred. + event_string, mods = self.utilities.lastKeyAndModifiers() + isControlKey = mods & keybindings.CTRL_MODIFIER_MASK + isShiftKey = mods & keybindings.SHIFT_MODIFIER_MASK + if event_string in ["Up", "Down"] and isControlKey and not isShiftKey: + string = self.utilities.displayedText(newLocusOfFocus) + if string: + voice = self.speechGenerator.voice(obj=newLocusOfFocus, string=string) + self.speakMessage(string, voice=voice) + self.updateBraille(newLocusOfFocus) + try: + text = newLocusOfFocus.queryText() + except Exception: + pass + else: + self._saveLastCursorPosition(newLocusOfFocus, text.caretOffset) + return + + # Pass the event onto the parent class to be handled in the default way. + default.Script.locusOfFocusChanged(self, event, + oldLocusOfFocus, newLocusOfFocus) + if not newLocusOfFocus: + return + + parent = AXObject.get_parent(newLocusOfFocus) + if parent is None: + return + + cell = None + if self.utilities.isTextDocumentCell(newLocusOfFocus): + cell = newLocusOfFocus + elif self.utilities.isTextDocumentCell(parent): + cell = parent + if cell: + row, column = self.utilities.coordinatesForCell(cell) + self.pointOfReference['lastRow'] = row + self.pointOfReference['lastColumn'] = column + + def onNameChanged(self, event): + """Called whenever a property on an object changes. + + Arguments: + - event: the Event + """ + + if self.spellcheck.isCheckWindow(event.source): + return + + # Impress slide navigation. + # + if self.utilities.isInImpress(event.source) \ + and self.utilities.isDrawingView(event.source): + title, position, count = \ + self.utilities.slideTitleAndPosition(event.source) + if title: + title += "." + + msg = messages.PRESENTATION_SLIDE_POSITION % \ + {"position" : position, "count" : count} + msg = self.utilities.appendString(title, msg) + self.presentMessage(msg) + + default.Script.onNameChanged(self, event) + + def onActiveChanged(self, event): + """Callback for object:state-changed:active accessibility events.""" + + if not AXObject.get_parent(event.source): + msg = "SOFFICE: Event source lacks parent" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + # Prevent this events from activating the find operation. + # See comment #18 of bug #354463. + if self.findCommandRun: + return + + default.Script.onActiveChanged(self, event) + + def onActiveDescendantChanged(self, event): + """Called when an object who manages its own descendants detects a + change in one of its children. + + Arguments: + - event: the Event + """ + + if self.utilities.isSameObject(event.any_data, cthulhu_state.locusOfFocus): + return + + if event.source == self.spellcheck.getSuggestionsList(): + if AXUtilities.is_focused(event.source): + cthulhu.setLocusOfFocus(event, event.any_data, False) + self.updateBraille(cthulhu_state.locusOfFocus) + self.spellcheck.presentSuggestionListItem() + else: + self.spellcheck.presentErrorDetails() + return + + if self.utilities.isSpreadSheetCell(event.any_data) \ + and not AXUtilities.is_focused(event.any_data) \ + and not AXUtilities.is_focused(event.source) : + msg = "SOFFICE: Neither source nor child have focused state. Clearing cache on table." + debug.printMessage(debug.LEVEL_INFO, msg, True) + AXObject.clear_cache(event.source) + + default.Script.onActiveDescendantChanged(self, event) + + def onChildrenAdded(self, event): + """Callback for object:children-changed:add accessibility events.""" + + AXObject.clear_cache_now("children-changed event.") + + if self.utilities.isSpreadSheetCell(event.any_data): + cthulhu.setLocusOfFocus(event, event.any_data) + return + + if self.utilities.isLastCell(event.any_data): + activeRow = self.pointOfReference.get('lastRow', -1) + activeCol = self.pointOfReference.get('lastColumn', -1) + if activeRow < 0 or activeCol < 0: + return + + if AXObject.is_dead(cthulhu_state.locusOfFocus): + cthulhu.setLocusOfFocus(event, event.source, False) + + self.utilities.handleUndoTextEvent(event) + rowCount, colCount = self.utilities.rowAndColumnCount(event.source) + if activeRow == rowCount: + full = messages.TABLE_ROW_DELETED_FROM_END + brief = messages.TABLE_ROW_DELETED + else: + full = messages.TABLE_ROW_INSERTED_AT_END + brief = messages.TABLE_ROW_INSERTED + self.presentMessage(full, brief) + return + + default.Script.onChildrenAdded(self, event) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # NOTE: This event type is deprecated and Cthulhu should no longer use it. + # This callback remains just to handle bugs in applications and toolkits + # during the remainder of the unstable (3.11) development cycle. + + if self.utilities.isSameObject(cthulhu_state.locusOfFocus, event.source): + return + + if self.utilities.isFocusableLabel(event.source): + cthulhu.setLocusOfFocus(event, event.source) + return + + role = AXObject.get_role(event.source) + + if self.utilities.isZombie(event.source) \ + or role in [Atspi.Role.TEXT, Atspi.Role.LIST]: + comboBox = self.utilities.containingComboBox(event.source) + if comboBox: + cthulhu.setLocusOfFocus(event, comboBox, True) + return + + # This seems to be something we inherit from Gtk+ + if role in [Atspi.Role.TEXT, Atspi.Role.PASSWORD_TEXT]: + cthulhu.setLocusOfFocus(event, event.source) + return + + # Ditto. + if role == Atspi.Role.PUSH_BUTTON: + cthulhu.setLocusOfFocus(event, event.source) + return + + # Ditto. + if role == Atspi.Role.TOGGLE_BUTTON: + cthulhu.setLocusOfFocus(event, event.source) + return + + # Ditto. + if role == Atspi.Role.COMBO_BOX: + cthulhu.setLocusOfFocus(event, event.source) + return + + # Ditto. + if role == Atspi.Role.PANEL and AXObject.get_name(event.source): + cthulhu.setLocusOfFocus(event, event.source) + return + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if self._inSayAll: + return + + if self._lastCommandWasStructNav: + return + + if not event.detail1: + return + + if self.utilities.isAnInputLine(event.source): + msg = "SOFFICE: Event ignored: spam from inputLine" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if AXObject.get_child_count(event.source) \ + and self.utilities.isAnInputLine(AXObject.get_child(event.source, 0)): + msg = "SOFFICE: Event ignored: spam from inputLine parent" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + role = AXObject.get_role(event.source) + if role in [Atspi.Role.TEXT, Atspi.Role.LIST]: + comboBox = self.utilities.containingComboBox(event.source) + if comboBox: + cthulhu.setLocusOfFocus(event, comboBox, True) + return + + parent = AXObject.get_parent(event.source) + if parent and AXObject.get_role(parent) == Atspi.Role.TOOL_BAR: + default.Script.onFocusedChanged(self, event) + return + + # TODO - JD: Verify this is still needed + ignoreRoles = [Atspi.Role.FILLER, Atspi.Role.PANEL] + if role in ignoreRoles: + return + + # We will present this when the selection changes. + if role == Atspi.Role.MENU: + return + + if self.utilities._flowsFromOrToSelection(event.source): + return + + if role == Atspi.Role.PARAGRAPH: + obj, offset = self.pointOfReference.get("lastCursorPosition", (None, -1)) + start, end, string = self.utilities.getCachedTextSelection(obj) + if start != end: + return + + keyString, mods = self.utilities.lastKeyAndModifiers() + if keyString in ["Left", "Right"]: + cthulhu.setLocusOfFocus(event, event.source, False) + return + + if self.utilities.isSpreadSheetTable(event.source) and cthulhu_state.locusOfFocus: + if AXObject.is_dead(cthulhu_state.locusOfFocus): + msg = "SOFFICE: Event believed to be post-editing focus claim. Dead locusOfFocus." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source, False) + return + if AXUtilities.is_paragraph(cthulhu_state.locusOfFocus) \ + or AXUtilities.is_table_cell(cthulhu_state.locusOfFocus): + msg = "SOFFICE: Event believed to be post-editing focus claim based on role." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source, False) + return + + default.Script.onFocusedChanged(self, event) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if event.detail1 == -1: + return + + if AXObject.get_role(event.source) == Atspi.Role.PARAGRAPH \ + and not AXUtilities.is_focused(event.source): + AXObject.clear_cache(event.source) + if AXUtilities.is_focused(event.source): + msg = "SOFFICE: Clearing cache was needed due to missing state-changed event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if self.utilities._flowsFromOrToSelection(event.source): + return + + if self._lastCommandWasStructNav: + return + + if self.utilities.isSpreadSheetCell(cthulhu_state.locusOfFocus): + tokens = ["SOFFICE: locusOfFocus", cthulhu_state.locusOfFocus, "is spreadsheet cell"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not self.utilities.isCellBeingEdited(event.source): + msg = "SOFFICE: Event ignored: Source is not cell being edited." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().onCaretMoved(event) + + def onCheckedChanged(self, event): + """Callback for object:state-changed:checked accessibility events.""" + + obj = event.source + role = AXObject.get_role(obj) + parentRole = AXObject.get_role(AXObject.get_parent(obj)) + if role not in [Atspi.Role.TOGGLE_BUTTON, Atspi.Role.PUSH_BUTTON] \ + or not parentRole == Atspi.Role.TOOL_BAR: + default.Script.onCheckedChanged(self, event) + return + + sourceWindow = self.utilities.topLevelObject(obj) + focusWindow = self.utilities.topLevelObject(cthulhu_state.locusOfFocus) + if sourceWindow != focusWindow: + return + + # Announce when the toolbar buttons are toggled if we just toggled + # them; not if we navigated to some text. + weToggledIt = False + if isinstance(cthulhu_state.lastInputEvent, input_event.MouseButtonEvent): + x = cthulhu_state.lastInputEvent.x + y = cthulhu_state.lastInputEvent.y + weToggledIt = obj.queryComponent().contains(x, y, 0) + elif AXUtilities.is_focused(obj): + weToggledIt = True + else: + keyString, mods = self.utilities.lastKeyAndModifiers() + navKeys = ["Up", "Down", "Left", "Right", "Page_Up", "Page_Down", + "Home", "End", "N"] + wasCommand = mods & keybindings.COMMAND_MODIFIER_MASK + weToggledIt = wasCommand and keyString not in navKeys + if weToggledIt: + self.presentObject(obj, alreadyFocused=True, interrupt=True) + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + full, brief = "", "" + if self.utilities.isSelectedTextDeletionEvent(event): + msg = "SOFFICE: Change is believed to be due to deleting selected text" + debug.printMessage(debug.LEVEL_INFO, msg, True) + full = messages.SELECTION_DELETED + elif self.utilities.isSelectedTextRestoredEvent(event): + msg = "SOFFICE: Selection is believed to be due to restoring selected text" + debug.printMessage(debug.LEVEL_INFO, msg, True) + if self.utilities.handleUndoTextEvent(event): + full = messages.SELECTION_RESTORED + + if full or brief: + self.presentMessage(full, brief) + self.utilities.updateCachedTextSelection(event.source) + return + + super().onSelectedChanged(event) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if self.utilities.isSpreadSheetTable(event.source): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return + if _settingsManager.getSetting('alwaysSpeakSelectedSpreadsheetRange'): + self.utilities.speakSelectedCellRange(event.source) + return + if self.utilities.handleRowAndColumnSelectionChange(event.source): + return + self.utilities.handleCellSelectionChange(event.source) + return + + if event.source == self.spellcheck.getSuggestionsList(): + if cthulhu_state.locusOfFocus == cthulhu_state.activeWindow: + msg = "SOFFICE: Not presenting because locusOfFocus is window" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif AXUtilities.is_focused(event.source): + cthulhu.setLocusOfFocus(event, event.any_data, False) + self.updateBraille(cthulhu_state.locusOfFocus) + self.spellcheck.presentSuggestionListItem() + else: + self.spellcheck.presentErrorDetails() + return + + if not self.utilities.isComboBoxSelectionChange(event): + super().onSelectionChanged(event) + return + + selectedChildren = self.utilities.selectedChildren(event.source) + if len(selectedChildren) == 1 \ + and self.utilities.containingComboBox(event.source) == \ + self.utilities.containingComboBox(cthulhu_state.locusOfFocus): + cthulhu.setLocusOfFocus(event, selectedChildren[0], True) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + if self.utilities.isComboBoxNoise(event): + msg = "SOFFICE: Event is believed to be combo box noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if AXObject.is_dead(event.source): + msg = "SOFFICE: Ignoring event from dead source." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if event.source != cthulhu_state.locusOfFocus \ + and AXUtilities.is_focused(event.source): + cthulhu.setLocusOfFocus(event, event.source, False) + + super().onTextSelectionChanged(event) + + def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None): + """To-be-removed. Returns the string, caretOffset, startOffset.""" + + if AXObject.get_role(AXObject.get_parent(obj)) == Atspi.Role.COMBO_BOX: + try: + text = obj.queryText() + except NotImplementedError: + return ["", 0, 0] + + if text.caretOffset < 0: + [lineString, startOffset, endOffset] = text.getTextAtOffset( + 0, Atspi.TextBoundaryType.LINE_START) + + # Sometimes we get the trailing line-feed -- remove it + # + if lineString[-1:] == "\n": + lineString = lineString[:-1] + + return [lineString, 0, startOffset] + + textLine = super().getTextLineAtCaret(obj, offset, startOffset, endOffset) + if not AXUtilities.is_focused(obj): + textLine[0] = self.utilities.displayedText(obj) + + return textLine + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + super().onWindowActivated(event) + if not self.spellcheck.isCheckWindow(event.source): + return + + child = AXObject.get_child(event.source, 0) + if AXObject.get_role(child) == Atspi.Role.DIALOG: + cthulhu.setLocusOfFocus(event, child, False) + + self.spellcheck.presentErrorDetails() + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + self._lastCommandWasStructNav = False + + super().onWindowDeactivated(event) + self.spellcheck.deactivate() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script_utilities.py new file mode 100644 index 0000000..e088aaa --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/script_utilities.py @@ -0,0 +1,815 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Commonly-required utility methods needed by -- and potentially + customized by -- application and toolkit scripts. They have + been pulled out from the scripts because certain scripts had + gotten way too large as a result of including these methods.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.debug as debug +import cthulhu.keybindings as keybindings +import cthulhu.messages as messages +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.script_utilities as script_utilities +from cthulhu.ax_object import AXObject +from cthulhu.ax_selection import AXSelection +from cthulhu.ax_utilities import AXUtilities + + +############################################################################# +# # +# Utilities # +# # +############################################################################# + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + """Creates an instance of the Utilities class. + + Arguments: + - script: the script with which this instance is associated. + """ + + script_utilities.Utilities.__init__(self, script) + + self._calcSelectedCells = [] + self._calcSelectedRows = [] + self._calcSelectedColumns = [] + + ######################################################################### + # # + # Utilities for finding, identifying, and comparing accessibles # + # # + ######################################################################### + + def displayedText(self, obj): + """Returns the text being displayed for an object. Overridden here + because OpenOffice uses symbols (e.g. ">>" for buttons but exposes + more useful information via the accessible's name. + + Arguments: + - obj: the object + + Returns the text being displayed for an object or None if there isn't + any text being shown. + """ + + name = AXObject.get_name(obj) + if name and AXUtilities.is_push_button(obj): + return name + + if AXUtilities.is_table_cell(obj): + strings = list(map(self.displayedText, [x for x in AXObject.iter_children(obj)])) + text = "\n".join(strings) + if text.strip(): + return text + + try: + text = super().displayedText(obj) + except Exception: + return "" + + # TODO - JD: This is needed because the default behavior is to fall + # back on the name, which is bogus. Once that has been fixed, this + # hack can go. + if AXUtilities.is_table_cell(obj) and text == name \ + and (self.isSpreadSheetCell(obj) or self.isTextDocumentCell(obj)): + return "" + + # More bogusness from (at least) Calc combined with the aforementioned + # fallback-to-name behavior.... + if self.isDocument(obj) and text == name and text.startswith("file:///"): + return "" + + return text + + def isCellBeingEdited(self, obj): + parent = AXObject.get_parent(obj) + if AXUtilities.is_panel(parent) or AXUtilities.is_extended(parent): + return self.spreadSheetCellName(parent) + + return False + + def spreadSheetCellName(self, cell): + nameList = AXObject.get_name(cell).split() + for name in nameList: + name = name.replace('.', '') + if not name.isalpha() and name.isalnum(): + return name + + return '' + + def getRowColumnAndTable(self, cell): + """Returns the (row, column, table) tuple for cell.""" + + if not AXUtilities.is_table_cell(cell): + return -1, -1, None + + cellParent = AXObject.get_parent(cell) + if AXUtilities.is_table_cell(cellParent): + cell = cellParent + cellParent = AXObject.get_parent(cell) + + table = cellParent + if table is not None and not AXUtilities.is_table(table): + table = AXObject.get_parent(table) + + try: + iTable = table.queryTable() + except Exception: + return -1, -1, None + + index = self.cellIndex(cell) + row = iTable.getRowAtIndex(index) + column = iTable.getColumnAtIndex(index) + + return row, column, table + + def rowHeadersForCell(self, obj): + rowHeader, colHeader = self.getDynamicHeadersForCell(obj) + if rowHeader: + return [rowHeader] + + return super().rowHeadersForCell(obj) + + def columnHeadersForCell(self, obj): + rowHeader, colHeader = self.getDynamicHeadersForCell(obj) + if colHeader: + return [colHeader] + + return super().columnHeadersForCell(obj) + + def getDynamicHeadersForCell(self, obj, onlyIfNew=False): + if not (self._script.dynamicRowHeaders or self._script.dynamicColumnHeaders): + return None, None + + objRow, objCol, table = self.getRowColumnAndTable(obj) + if not table: + return None, None + + headersRow = self._script.dynamicColumnHeaders.get(hash(table)) + headersCol = self._script.dynamicRowHeaders.get(hash(table)) + if headersRow == objRow or headersCol == objCol: + return None, None + + getRowHeader = headersCol is not None + getColHeader = headersRow is not None + if onlyIfNew: + getRowHeader = \ + getRowHeader and objRow != self._script.pointOfReference.get("lastRow") + getColHeader = \ + getColHeader and objCol!= self._script.pointOfReference.get("lastColumn") + + parentTable = table.queryTable() + rowHeader, colHeader = None, None + if getColHeader: + colHeader = parentTable.getAccessibleAt(headersRow, objCol) + + if getRowHeader: + rowHeader = parentTable.getAccessibleAt(objRow, headersCol) + + return rowHeader, colHeader + + def isSameObject(self, obj1, obj2, comparePaths=False, ignoreNames=False, + ignoreDescriptions=True): + if obj1 == obj2: + return True + + if not AXUtilities.have_same_role(obj1, obj2): + return False + + if AXUtilities.is_paragraph(obj1): + return False + + name = AXObject.get_name(obj1) + if name == AXObject.get_name(obj2): + if AXUtilities.is_frame(obj1): + return True + if AXUtilities.is_table_cell(obj1) and not name: + if self.isZombie(obj1) and self.isZombie(obj2): + return False + + return super().isSameObject(obj1, obj2, comparePaths, ignoreNames) + + def isLayoutOnly(self, obj): + """Returns True if the given object is a container which has + no presentable information (label, name, displayed text, etc.).""" + + if AXUtilities.is_list(obj): + if AXUtilities.is_combo_box(AXObject.get_parent(obj)): + return True + return super().isLayoutOnly(obj) + + name = AXObject.get_name(obj) + if not name: + return super().isLayoutOnly(obj) + + if AXUtilities.is_frame(obj): + return name == AXObject.get_name(cthulhu_state.activeWindow) + + if AXUtilities.is_panel(obj) and AXObject.get_child_count(obj): + if AXObject.get_name(AXObject.get_child(obj, 0)) == name: + return True + + return super().isLayoutOnly(obj) + + def isAnInputLine(self, obj): + if not obj: + return False + if obj == self.locateInputLine(obj): + return True + + parent = AXObject.get_parent(obj) + if AXUtilities.is_panel(parent) or AXUtilities.is_extended(parent): + if self.spreadSheetCellName(parent): + return False + + parent = AXObject.get_parent(parent) + if AXUtilities.is_text(parent): + return True + + return False + + def locateInputLine(self, obj): + """Return the spread sheet input line. This only needs to be found + the very first time a spread sheet table cell gets focus. We use the + table cell to work back up the component hierarchy until we have found + the common panel that both it and the input line reside in. We then + use that as the base component to search for a component which has a + paragraph role. This will be the input line. + + Arguments: + - obj: the spread sheet table cell that has just got focus. + + Returns the spread sheet input line component. + """ + + if self._script.inputLineForCell is not None: + topLevel = self.topLevelObject(self._script.inputLineForCell) + if self.isSameObject(cthulhu_state.activeWindow, topLevel): + return self._script.inputLineForCell + + scrollPane = AXObject.find_ancestor(obj, AXUtilities.is_scroll_pane) + if scrollPane is None: + return None + + toolbar = None + for child in AXObject.iter_children(AXObject.get_parent(scrollPane), + AXUtilities.is_tool_bar): + toolbar = child + break + + if toolbar is None: + msg = "ERROR: Calc inputline toolbar not found." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None + + allParagraphs = self.findAllDescendants(toolbar, AXUtilities.is_paragraph) + if len(allParagraphs) == 1: + self._script.inputLineForCell = allParagraphs[0] + + return self._script.inputLineForCell + + def frameAndDialog(self, obj): + """Returns the frame and (possibly) the dialog containing + the object. Overridden here for presentation of the title + bar information: If the locusOfFocus is a spreadsheet cell, + 1) we are not in a dialog and 2) we need to present both the + frame name and the sheet name. So we might as well return the + sheet in place of the dialog so that the default code can do + its thing. + """ + + if not self.isSpreadSheetCell(obj): + return script_utilities.Utilities.frameAndDialog(self, obj) + + results = [None, None] + + parent = AXObject.get_parent_checked(obj) + while parent: + if AXObject.get_role(parent) == Atspi.Role.FRAME: + results[0] = parent + if AXObject.get_role(parent) == Atspi.Role.TABLE: + results[1] = parent + parent = AXObject.get_parent_checked(parent) + + return results + + @staticmethod + def _flowsFromOrToSelection(obj): + relationSet = AXObject.get_relations(obj) + flows = [Atspi.RelationType.FLOWS_FROM, Atspi.RelationType.FLOWS_TO] + relations = filter(lambda r: r.getRelationType() in flows, relationSet) + targets = [r.getTarget(0) for r in relations] + for target in targets: + try: + nSelections = target.queryText().getNSelections() + except Exception: + return False + if nSelections: + return True + + return False + + def objectContentsAreInClipboard(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + if not obj: + return False + + if self.isSpreadSheetCell(obj): + contents = self.getClipboardContents() + string = self.displayedText(obj) or "\n" + return string in contents + + return super().objectContentsAreInClipboard(obj) + + ######################################################################### + # # + # Impress-Specific Utilities # + # # + ######################################################################### + + def drawingView(self, obj=cthulhu_state.locusOfFocus): + """Attempts to locate the Impress drawing view, which is the + area in which slide editing occurs.""" + + return AXObject.find_descendant(self.topLevelObject(obj), self.isDrawingView) + + def isDrawingView(self, obj): + """Returns True if obj is the Impress Drawing View.""" + + if self.isDocument(obj): + name = AXObject.get_name(obj) + return ":" in name and "/" in name + + return False + + def isInImpress(self, obj=cthulhu_state.locusOfFocus): + """Returns True if obj is in OOo Impress.""" + + # Having checked English, Spanish, and Arabic, it would seem + # that the Frame name will end with "Impress", unlocalized. + # + if obj: + try: + topLevel = self.topLevelObject(obj) + except Exception: + tokens = ["ERROR: Exception getting top-level object for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + if not topLevel: + return False + if AXObject.is_dead(topLevel): + tokens = ["SOFFICE: Top level object", topLevel, "is dead."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + if AXObject.get_name(topLevel).endswith("Impress"): + return True + + return False + + def slideAndTaskPanes(self, obj=cthulhu_state.locusOfFocus): + """Attempts to locate the Impress slide pane and task pane.""" + + drawingView = self.drawingView(obj) + if not drawingView: + return None, None + + parent = AXObject.get_parent(drawingView) + if parent: + parent = AXObject.get_parent(parent) + if not parent: + return None, None + + panes = self.findAllDescendants(parent, AXUtilities.is_split_pane) + if not panes: + return None, None + + slidePane = taskPane = None + if self.findAllDescendants(panes[0], self.isDocument): + slidePane = panes[0] + if len(panes) == 2: + taskPane = panes[1] + else: + taskPane = panes[0] + if len(panes) == 2: + slidePane = panes[1] + + return slidePane, taskPane + + def slideTitleAndPosition(self, obj): + """Attempts to obtain the title, position of the slide which contains + or is represented by obj. + + Returns a (title, position, count) tuple. + """ + + dv = self.getDocumentForObject(obj) + if not dv or not self.isDrawingView(dv): + return "", 0, 0 + + positionAndCount = AXObject.get_name(dv).split(":")[1] + position, count = positionAndCount.split("/") + title = "" + for child in dv: + childCount = AXObject.get_child_count(child) + if not childCount: + continue + # We want an actual Title. + # + if AXObject.get_name(child).startswith("ImpressTitle"): + title = self.displayedText(AXObject.get_child(child, 0)) + break + # But we'll live with a Subtitle if we can't find a title. + # Unlike Titles, a single subtitle can be made up of multiple + # accessibles. + # + elif AXObject.get_name(child).startswith("ImpressSubtitle"): + for i in range(childCount): + line = AXObject.get_child(child, i) + title = self.appendString(title, self.displayedText(line)) + + return title, int(position), int(count) + + ######################################################################### + # # + # Miscellaneous Utilities # + # # + ######################################################################### + + def isAutoTextEvent(self, event): + """Returns True if event is associated with text being autocompleted + or autoinserted or autocorrected or autosomethingelsed. + + Arguments: + - event: the accessible event being examined + """ + + if AXObject.get_role(event.source) != Atspi.Role.PARAGRAPH: + return False + + lastKey, mods = self.lastKeyAndModifiers() + if event.type.startswith("object:text-changed:insert"): + if not event.any_data: + return False + + if lastKey == "Tab" and event.any_data != "\t": + return True + + if lastKey in ["BackSpace", "ISO_Left_Tab"]: + return True + + if event.type.startswith("focus:"): + if lastKey == "Return": + try: + charCount = event.source.queryText().characterCount + except Exception: + charCount = 0 + return charCount > 0 + + return False + + def containingComboBox(self, obj): + if AXUtilities.is_combo_box(obj): + comboBox = obj + else: + comboBox = AXObject.find_ancestor(obj, AXUtilities.is_combo_box) + + if not comboBox: + return None + + if not self.isZombie(comboBox): + return comboBox + + parent = AXObject.get_parent(comboBox) + if not parent: + return comboBox + + replicant = self.findReplicant(parent, comboBox) + if replicant and not self.isZombie(replicant): + comboBox = replicant + + return comboBox + + def isComboBoxSelectionChange(self, event): + comboBox = self.containingComboBox(event.source) + if not comboBox: + return False + + lastKey, mods = self.lastKeyAndModifiers() + if lastKey not in ["Down", "Up"]: + return False + + return True + + def isComboBoxNoise(self, event): + role = AXObject.get_role(event.source) + if role == Atspi.Role.TEXT and event.type.startswith("object:text-"): + return self.isComboBoxSelectionChange(event) + + return False + + def isPresentableTextChangedEventForLocusOfFocus(self, event): + if self.isComboBoxNoise(event): + msg = "SOFFICE: Event is believed to be combo box noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + return super().isPresentableTextChangedEventForLocusOfFocus(event) + + def isReadOnlyTextArea(self, obj): + if not super().isReadOnlyTextArea(obj): + return False + + return not self.inDocumentContent(obj) + + def isSelectedTextDeletionEvent(self, event): + if event.type.startswith("object:state-changed:selected") and not event.detail1: + return AXObject.is_dead(cthulhu_state.locusOfFocus) and self.lastInputEventWasDelete() + + return super().isSelectedTextDeletionEvent(event) + + def lastInputEventWasRedo(self): + if super().lastInputEventWasRedo(): + return True + + keyString, mods = self.lastKeyAndModifiers() + if mods & keybindings.COMMAND_MODIFIER_MASK and keyString.lower() == 'y': + return not (mods & keybindings.SHIFT_MODIFIER_MASK) + + return False + + def selectedChildren(self, obj): + # TODO - JD: Are these overrides still needed? They appear to be + # quite old. + + if obj is None: + return [] + + if not AXObject.supports_selection(obj) and AXUtilities.is_combo_box(obj): + child = AXObject.find_descendant(obj, AXObject.supports_selection) + if child: + return super().selectedChildren(child) + + # Things only seem broken for certain tables, e.g. the Paths table. + # TODO - JD: File the LibreOffice bugs and reference them here. + if not AXUtilities.is_table(obj): + return super().selectedChildren(obj) + + # We will need to special case this due to the possibility of there + # being lots of children (which may also prove to be zombie objects). + # This is why we can't have nice things. + if self.isSpreadSheetTable(obj): + return [] + + return AXSelection.get_selected_children(obj) + + def getFirstCaretPosition(self, obj): + try: + obj.queryText() + except Exception: + if AXObject.get_child_count(obj): + return self.getFirstCaretPosition(AXObject.get_child(obj, 0)) + + return obj, 0 + + def getWordAtOffsetAdjustedForNavigation(self, obj, offset=None): + return self.getWordAtOffset(obj, offset) + + def shouldReadFullRow(self, obj): + if self._script._lastCommandWasStructNav: + return False + + lastKey, mods = self.lastKeyAndModifiers() + if lastKey in ["Tab", "ISO_Left_Tab"]: + return False + + return super().shouldReadFullRow(obj) + + def presentEventFromNonShowingObject(self, event): + return self.inDocumentContent(event.source) + + def columnConvert(self, column): + """ Convert a spreadsheet column into it's column label.""" + + base26 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + if column <= len(base26): + return base26[column-1] + + res = "" + while column > 0: + digit = column % len(base26) + res = " " + base26[digit-1] + res + column = int(column / len(base26)) + + return res + + def _getCellNameForCoordinates(self, obj, row, col, includeContents=False): + try: + table = obj.queryTable() + except Exception: + tokens = ["SOFFICE: Exception querying Table interface of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + try: + cell = table.getAccessibleAt(row, col) + except Exception: + tokens = [f"SOFFICE: Exception getting cell ({row},{col}) of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + name = self.spreadSheetCellName(cell) + if includeContents: + text = self.displayedText(cell) + name = f"{text} {name}" + + return name.strip() + + def _getCoordinatesForSelectedRange(self, obj): + if not (AXObject.supports_table(obj) and AXObject.supports_selection(obj)): + tokens = ["SOFFICE:", obj, "does not implement both selection and table"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return (-1, -1), (-1, -1) + + first = AXSelection.get_selected_child(obj, 0) + last = AXSelection.get_selected_child(obj, -1) + firstCoords = self.coordinatesForCell(first) + lastCoords = self.coordinatesForCell(last) + return firstCoords, lastCoords + + def getSelectionContainer(self, obj): + # Writer implements the selection interface on the document and all its + # children. The former is interesting, but interferes with our presentation + # of selected text. The latter is just weird. + if AXUtilities.is_document_text(obj): + return None + if AXObject.find_ancestor(obj, AXUtilities.is_document_text): + return None + return super().getSelectionContainer(obj) + + def speakSelectedCellRange(self, obj): + firstCoords, lastCoords = self._getCoordinatesForSelectedRange(obj) + if firstCoords == (-1, -1) or lastCoords == (-1, -1): + return False + + self._script.presentationInterrupt() + + if firstCoords == lastCoords: + cell = self._getCellNameForCoordinates(obj, *firstCoords, True) + self._script.speakMessage(messages.CELL_SELECTED % cell) + return True + + cell1 = self._getCellNameForCoordinates(obj, *firstCoords, True) + cell2 = self._getCellNameForCoordinates(obj, *lastCoords, True) + self._script.speakMessage(messages.CELL_RANGE_SELECTED % (cell1, cell2)) + return True + + def handleCellSelectionChange(self, obj): + firstCoords, lastCoords = self._getCoordinatesForSelectedRange(obj) + if firstCoords == (-1, -1) or lastCoords == (-1, -1): + return True + + current = [] + for r in range(firstCoords[0], lastCoords[0]+1): + current.extend((r, c) for c in range(firstCoords[1], lastCoords[1]+1)) + + current = set(current) + previous = set(self._calcSelectedCells) + current.discard((-1, -1)) + previous.discard((-1, -1)) + + unselected = sorted(previous.difference(current)) + selected = sorted(current.difference(previous)) + focusCoords = tuple(self.coordinatesForCell(cthulhu_state.locusOfFocus)) + if focusCoords in selected: + selected.remove(focusCoords) + + self._calcSelectedCells = sorted(current) + + msgs = [] + if len(unselected) == 1: + cell = self._getCellNameForCoordinates(obj, *unselected[0], True) + msgs.append(messages.CELL_UNSELECTED % cell) + elif len(unselected) > 1: + cell1 = self._getCellNameForCoordinates(obj, *unselected[0], True) + cell2 = self._getCellNameForCoordinates(obj, *unselected[-1], True) + msgs.append(messages.CELL_RANGE_UNSELECTED % (cell1, cell2)) + + if len(selected) == 1: + cell = self._getCellNameForCoordinates(obj, *selected[0], True) + msgs.append(messages.CELL_SELECTED % cell) + elif len(selected) > 1: + cell1 = self._getCellNameForCoordinates(obj, *selected[0], True) + cell2 = self._getCellNameForCoordinates(obj, *selected[-1], True) + msgs.append(messages.CELL_RANGE_SELECTED % (cell1, cell2)) + + if msgs: + self._script.presentationInterrupt() + + for msg in msgs: + self._script.speakMessage(msg, interrupt=False) + + return bool(len(msgs)) + + def handleRowAndColumnSelectionChange(self, obj): + if not (AXObject.supports_table(obj) and AXObject.supports_selection(obj)): + return True + + table = obj.queryTable() + cols = set(table.getSelectedColumns()) + rows = set(table.getSelectedRows()) + + selectedCols = sorted(cols.difference(set(self._calcSelectedColumns))) + unselectedCols = sorted(set(self._calcSelectedColumns).difference(cols)) + + def convertColumn(x): + return self.columnConvert(x+1) + + def convertRow(x): + return x + 1 + + selectedCols = list(map(convertColumn, selectedCols)) + unselectedCols = list(map(convertColumn, unselectedCols)) + + selectedRows = sorted(rows.difference(set(self._calcSelectedRows))) + unselectedRows = sorted(set(self._calcSelectedRows).difference(rows)) + + selectedRows = list(map(convertRow, selectedRows)) + unselectedRows = list(map(convertRow, unselectedRows)) + + self._calcSelectedColumns = list(cols) + self._calcSelectedRows = list(rows) + + if len(cols) == table.nColumns: + self._script.speakMessage(messages.DOCUMENT_SELECTED_ALL) + return True + + if not len(cols) and len(unselectedCols) == table.nColumns: + self._script.speakMessage(messages.DOCUMENT_UNSELECTED_ALL) + return True + + msgs = [] + if len(unselectedCols) == 1: + msgs.append(messages.TABLE_COLUMN_UNSELECTED % unselectedCols[0]) + elif len(unselectedCols) > 1: + msgs.append(messages.TABLE_COLUMN_RANGE_UNSELECTED % \ + (unselectedCols[0], unselectedCols[-1])) + + if len(unselectedRows) == 1: + msgs.append(messages.TABLE_ROW_UNSELECTED % unselectedRows[0]) + elif len(unselectedRows) > 1: + msgs.append(messages.TABLE_ROW_RANGE_UNSELECTED % \ + (unselectedRows[0], unselectedRows[-1])) + + if len(selectedCols) == 1: + msgs.append(messages.TABLE_COLUMN_SELECTED % selectedCols[0]) + elif len(selectedCols) > 1: + msgs.append(messages.TABLE_COLUMN_RANGE_SELECTED % (selectedCols[0], selectedCols[-1])) + + if len(selectedRows) == 1: + msgs.append(messages.TABLE_ROW_SELECTED % selectedRows[0]) + elif len(selectedRows) > 1: + msgs.append(messages.TABLE_ROW_RANGE_SELECTED % (selectedRows[0], selectedRows[-1])) + + if msgs: + self._script.presentationInterrupt() + + for msg in msgs: + self._script.speakMessage(msg, interrupt=False) + + return bool(len(msgs)) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/speech_generator.py new file mode 100644 index 0000000..e7afee9 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/speech_generator.py @@ -0,0 +1,517 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for StarOffice and OpenOffice.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.messages as messages +import cthulhu.settings_manager as settings_manager +import cthulhu.speech_generator as speech_generator +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +class SpeechGenerator(speech_generator.SpeechGenerator): + def __init__(self, script): + speech_generator.SpeechGenerator.__init__(self, script) + + def __overrideParagraph(self, obj, **args): + # Treat a paragraph which is serving as a text entry in a dialog + # as a text object. + # + role = args.get('role', AXObject.get_role(obj)) + if role == "text frame": + return True + if role != Atspi.Role.PARAGRAPH: + return False + return AXObject.find_ancestor(obj, AXUtilities.is_dialog) is not None + + def _generateRoleName(self, obj, **args): + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.TOGGLE_BUTTON \ + and AXObject.get_role(AXObject.get_parent(obj)) == Atspi.Role.TOOL_BAR: + pass + else: + # Treat a paragraph which is serving as a text entry in a dialog + # as a text object. + # + override = self.__overrideParagraph(obj, **args) + if override: + oldRole = self._overrideRole(Atspi.Role.TEXT, args) + # Treat a paragraph which is inside of a spreadsheet cell as + # a spreadsheet cell. + # + elif role == 'ROLE_SPREADSHEET_CELL': + oldRole = self._overrideRole(Atspi.Role.TABLE_CELL, args) + override = True + result.extend(speech_generator.SpeechGenerator._generateRoleName( + self, obj, **args)) + if override: + self._restoreRole(oldRole, args) + return result + + def _generateTextRole(self, obj, **args): + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.TEXT \ + and AXObject.get_role(AXObject.get_parent(obj)) == Atspi.Role.COMBO_BOX: + return [] + + if role != Atspi.Role.PARAGRAPH \ + or self.__overrideParagraph(obj, **args): + result.extend(self._generateRoleName(obj, **args)) + return result + + def _generateLabel(self, obj, **args): + """Returns the label for an object as an array of strings (and + possibly voice and audio specifications). The label is + determined by the displayedLabel method of the script utility, + and an empty array will be returned if no label can be found. + """ + result = [] + override = self.__overrideParagraph(obj, **args) + label = self._script.utilities.displayedLabel(obj) or "" + if not label and override: + label = self._script.utilities.displayedLabel(AXObject.get_parent(obj)) or "" + if label: + result.append(label.strip()) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + return result + + def _generateName(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the name of the object. If the object is directly + displaying any text, that text will be treated as the name. + Otherwise, the accessible name of the object will be used. If + there is no accessible name, then the description of the + object will be used. This method will return an empty array + if nothing can be found. + """ + + # TODO - JD: This should be the behavior by default. But the default + # generators call displayedText(). Once that is corrected, this method + # can be removed. + if AXObject.get_name(obj): + result = [AXObject.get_name(obj)] + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + return result + + return super()._generateName(obj, **args) + + def _generateLabelAndName(self, obj, **args): + if AXObject.get_role(obj) != Atspi.Role.COMBO_BOX: + return super()._generateLabelAndName(obj, **args) + + # TODO - JD: This should be the behavior by default because many + # toolkits use the label for the name. + result = [] + label = self._script.utilities.displayedLabel(obj) or AXObject.get_name(obj) + if label: + result.append(label) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + + name = AXObject.get_name(obj) + if label == name or not name: + selected = self._script.utilities.selectedChildren(obj) + if selected: + name = AXObject.get_name(selected[0]) + + if name: + result.append(name) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + + return result + + def _generateLabelOrName(self, obj, **args): + """Gets the label or the name if the label is not preset.""" + + result = [] + override = self.__overrideParagraph(obj, **args) + # Treat a paragraph which is serving as a text entry in a dialog + # as a text object. + # + if override: + result.extend(self._generateLabel(obj, **args)) + if len(result) == 0 and AXObject.get_parent(obj): + parentLabel = self._generateLabel(AXObject.get_parent(obj), **args) + # If we aren't already focused, we will have spoken the + # parent as part of the speech context and do not want + # to repeat it. + # + alreadyFocused = args.get('alreadyFocused', False) + if alreadyFocused: + result.extend(parentLabel) + # If we still don't have a label, look to the name. + # + if not parentLabel: + name = AXObject.get_name(obj) + if name: + result.append(name) + if result: + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + else: + result.extend(speech_generator.SpeechGenerator._generateLabelOrName( + self, obj, **args)) + return result + + def _generateAnyTextSelection(self, obj, **args): + comboBoxEntry = self._script.utilities.getEntryForEditableComboBox(obj) + if comboBoxEntry: + return super()._generateAnyTextSelection(comboBoxEntry) + + return super()._generateAnyTextSelection(obj, **args) + + def _generateAvailability(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the grayed/sensitivity/availability state of the + object, but only if it is insensitive (i.e., grayed out and + inactive). Otherwise, and empty array will be returned. + """ + + result = [] + if not self._script.utilities.isSpreadSheetCell(obj): + result.extend(speech_generator.SpeechGenerator.\ + _generateAvailability(self, obj, **args)) + + return result + + def _generateDescription(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the description of the object, + if that description is different from that of the name and + label. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not _settingsManager.getSetting('speakDescription'): + return [] + + if not args.get('formatType', '').endswith('WhereAmI'): + return [] + + result = [] + description = AXObject.get_description(obj) + if description: + # The description of some OOo paragraphs consists of the name + # and the displayed text, with punctuation added. Try to spot + # this and, if found, ignore the description. + # + text = self._script.utilities.displayedText(obj) or "" + desc = description.replace(text, "") + for item in AXObject.get_name(obj).split(): + desc = desc.replace(item, "") + for char in desc.strip(): + if char.isalnum(): + result.append(description) + break + + if result: + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + def _generateCurrentLineText(self, obj, **args): + if self._script.utilities.isTextDocumentCell(AXObject.get_parent(obj)): + priorObj = args.get('priorObj', None) + if priorObj and AXObject.get_parent(priorObj) != AXObject.get_parent(obj): + return [] + + if AXObject.get_role(obj) == Atspi.Role.COMBO_BOX: + entry = self._script.utilities.getEntryForEditableComboBox(obj) + if entry: + return super()._generateCurrentLineText(entry) + return [] + + # TODO - JD: The SayLine, etc. code should be generated and not put + # together in the scripts. In addition, the voice crap needs to go + # here. Then it needs to be removed from the scripts. + [text, caretOffset, startOffset] = self._script.getTextLineAtCaret(obj) + if not text: + result = [messages.BLANK] + result.extend(self.voice(string=text, obj=obj, **args)) + return result + + return super()._generateCurrentLineText(obj, **args) + + def _generateToggleState(self, obj, **args): + """Treat toggle buttons in the toolbar specially. This is so we can + have more natural sounding speech such as "bold on", "bold off", etc.""" + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.TOGGLE_BUTTON \ + and AXObject.get_role(AXObject.get_parent(obj)) == Atspi.Role.TOOL_BAR: + if AXUtilities.is_checked(obj): + result.append(messages.ON) + else: + result.append(messages.OFF) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + elif role == Atspi.Role.TOGGLE_BUTTON: + result.extend(speech_generator.SpeechGenerator._generateToggleState( + self, obj, **args)) + return result + + def _generateRowHeader(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the row header for an object + that is in a table, if it exists. Otherwise, an empty array + is returned. Overridden here so that we can get the dynamic + row header(s). + """ + + if self._script.utilities.shouldReadFullRow(obj): + return [] + + newOnly = args.get('newOnly', False) + rowHeader, columnHeader = \ + self._script.utilities.getDynamicHeadersForCell(obj, newOnly) + if not rowHeader: + return super()._generateRowHeader(obj, **args) + + result = [] + text = self._script.utilities.displayedText(rowHeader) + if text: + result.append(text) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + + return result + + def _generateColumnHeader(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the column header for an object + that is in a table, if it exists. Otherwise, an empty array + is returned. Overridden here so that we can get the dynamic + column header(s). + """ + + newOnly = args.get('newOnly', False) + rowHeader, columnHeader = \ + self._script.utilities.getDynamicHeadersForCell(obj, newOnly) + if not columnHeader: + return super()._generateColumnHeader(obj, **args) + + result = [] + text = self._script.utilities.displayedText(columnHeader) + if text: + result.append(text) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + + return result + + def _generateTooLong(self, obj, **args): + """If there is text in this spread sheet cell, compare the size of + the text within the table cell with the size of the actual table + cell and report back to the user if it is larger. + + Returns an indication of how many characters are greater than the size + of the spread sheet cell, or None if the message fits. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + try: + text = obj.queryText() + objectText = \ + self._script.utilities.substring(obj, 0, -1) + extents = obj.queryComponent().getExtents(Atspi.CoordType.SCREEN) + except NotImplementedError: + pass + else: + tooLongCount = 0 + for i in range(0, len(objectText)): + [x, y, width, height] = text.getRangeExtents(i, i + 1, 0) + if x < extents.x: + tooLongCount += 1 + elif (x + width) > extents.x + extents.width: + tooLongCount += len(objectText) - i + break + if tooLongCount > 0: + result = [messages.charactersTooLong(tooLongCount)] + if result: + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + def _generateHasFormula(self, obj, **args): + inputLine = self._script.utilities.locateInputLine(obj) + if not inputLine: + return [] + + text = self._script.utilities.displayedText(inputLine) + if text and text.startswith("="): + result = [messages.HAS_FORMULA] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + return [] + + def _generateRealTableCell(self, obj, **args): + """Get the speech for a table cell. If this isn't inside a + spread sheet, just return the utterances returned by the default + table cell speech handler. + + Arguments: + - obj: the table cell + + Returns a list of utterances to be spoken for the object. + """ + + if self._script.inSayAll(): + return [] + + result = super()._generateRealTableCell(obj, **args) + + if not self._script.utilities.isSpreadSheetCell(obj): + if self._script._lastCommandWasStructNav: + return result + + if _settingsManager.getSetting('speakCellCoordinates'): + result.append(AXObject.get_name(obj)) + return result + + isBasicWhereAmI = args.get('formatType') == 'basicWhereAmI' + speakCoordinates = _settingsManager.getSetting('speakSpreadsheetCoordinates') + if speakCoordinates and not isBasicWhereAmI: + result.append(self._script.utilities.spreadSheetCellName(obj)) + + if self._script.utilities.shouldReadFullRow(obj): + row, col, table = self._script.utilities.getRowColumnAndTable(obj) + lastRow = self._script.pointOfReference.get("lastRow") + if row != lastRow: + return result + + tooLong = self._generateTooLong(obj, **args) + if tooLong: + result.extend(self._generatePause(obj, **args)) + result.extend(tooLong) + + hasFormula = self._generateHasFormula(obj, **args) + if hasFormula: + result.extend(self._generatePause(obj, **args)) + result.extend(hasFormula) + + return result + + def _generateTableCellRow(self, obj, **args): + if not self._script.utilities.shouldReadFullRow(obj): + return self._generateRealTableCell(obj, **args) + + if not self._script.utilities.isSpreadSheetCell(obj): + return super()._generateTableCellRow(obj, **args) + + cells = self._script.utilities.getShowingCellsInSameRow(obj) + if not cells: + return [] + + result = [] + for cell in cells: + result.extend(self._generateRealTableCell(cell, **args)) + + return result + + def _generateEndOfTableIndicator(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) indicating that this cell is the last cell + in the table. Overridden here because Cthulhu keeps saying "end + of table" in certain lists (e.g. the Templates and Documents + dialog). + """ + + if self._script._lastCommandWasStructNav or self._script.inSayAll(): + return [] + + topLevel = self._script.utilities.topLevelObject(obj) + if topLevel and AXObject.get_role(topLevel) == Atspi.Role.DIALOG: + return [] + + return super()._generateEndOfTableIndicator(obj, **args) + + def _generateNewAncestors(self, obj, **args): + priorObj = args.get('priorObj', None) + if not priorObj or AXObject.get_role_name(priorObj) == 'text frame': + return [] + + if self._script.utilities.isSpreadSheetCell(obj) \ + and self._script.utilities.isDocumentPanel(AXObject.get_parent(priorObj)): + return [] + + return super()._generateNewAncestors(obj, **args) + + def _generateOldAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object being left.""" + + if AXObject.get_role_name(obj) == 'text frame': + return [] + + priorObj = args.get('priorObj', None) + if self._script.utilities.isSpreadSheetCell(priorObj): + return [] + + return super()._generateOldAncestors(obj, **args) + + def _generateUnselectedCell(self, obj, **args): + if self._script.utilities.isSpreadSheetCell(obj): + return [] + + if self._script._lastCommandWasStructNav: + return [] + + return super()._generateUnselectedCell(obj, **args) + + def generateSpeech(self, obj, **args): + result = [] + if args.get('formatType', 'unfocused') == 'basicWhereAmI' \ + and self._script.utilities.isSpreadSheetCell(obj): + oldRole = self._overrideRole('ROLE_SPREADSHEET_CELL', args) + # In addition, if focus is in a cell being edited, we cannot + # query the accessible table interface for coordinates and the + # like because we're temporarily in an entirely different object + # which is outside of the table. This makes things difficult. + # However, odds are that if we're doing a whereAmI in a cell + # which we are editing, we have some pointOfReference info + # we can use to guess the coordinates. + # + args['guessCoordinates'] = AXObject.get_role(obj) == Atspi.Role.PARAGRAPH + result.extend(super().generateSpeech(obj, **args)) + del args['guessCoordinates'] + self._restoreRole(oldRole, args) + else: + oldRole = self._overrideRole(self._getAlternativeRole(obj, **args), args) + result.extend(super().generateSpeech(obj, **args)) + self._restoreRole(oldRole, args) + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/spellcheck.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/spellcheck.py new file mode 100644 index 0000000..3bf0fe3 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/soffice/spellcheck.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Customized support for spellcheck in LibreOffice.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2015 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu import debug +from cthulhu import messages +from cthulhu import spellcheck +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +class SpellCheck(spellcheck.SpellCheck): + + def __init__(self, script): + super().__init__(script, hasChangeToEntry=False) + self._windows = {} + + def _findChildDialog(self, root): + if root is None: + return None + + if AXUtilities.is_dialog(root): + return root + + return self._findChildDialog(AXObject.get_child(root, 0)) + + def _isCandidateWindow(self, window): + if AXObject.is_dead(window): + tokens = ["SOFFICE:", window, "is not spellcheck window because it's dead."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + rv = self._windows.get(hash(window)) + if rv is not None: + tokens = ["SOFFICE:", window, "is spellcheck window:", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + dialog = self._findChildDialog(window) + if not dialog: + self._windows[hash(window)] = False + tokens = ["SOFFICE:", window, + "is not spellcheck window because the dialog was not found."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if AXObject.find_descendant(dialog, AXUtilities.is_page_tab_list) is not None: + self._windows[hash(window)] = False + self._windows[hash(dialog)] = False + tokens = ["SOFFICE:", dialog, + "is not spellcheck dialog because a page tab list was found."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + rv = AXObject.find_descendant(dialog, AXUtilities.is_combo_box) is not None + tokens = ["SOFFICE:", dialog, "is spellcheck dialog based on combobox descendant:", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._windows[hash(dialog)] = rv + return rv + + def _findErrorWidget(self, root): + def isError(x): + if not AXObject.supports_editable_text(x): + return False + return AXUtilities.is_focusable(x) and AXUtilities.is_multi_line(x) + + rv = AXObject.find_descendant(root, isError) + tokens = ["SOFFICE: Error widget for:", root, "is:", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def _findSuggestionsList(self, root): + def isSelectableList(x): + if not AXObject.supports_selection(x): + return False + return AXUtilities.is_list(x) \ + or AXUtilities.is_list_box(x) \ + or AXUtilities.is_tree_table(x) + + rv = AXObject.find_descendant(root, isSelectableList) + tokens = ["SOFFICE: Suggestions list for:", root, "is:", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def _getSuggestionIndexAndPosition(self, suggestion): + index, total = self._script.utilities.getPositionAndSetSize(suggestion) + return index + 1, total + + def getMisspelledWord(self): + try: + text = self._errorWidget.queryText() + except Exception: + return "" + + offset, string = 0, "" + while 0 <= offset < text.characterCount: + attributes, start, end = text.getAttributeRun(offset, False) + attrs = dict([attr.split(":", 1) for attr in attributes]) + if attrs.get("fg-color", "").replace(" ", "") == "255,0,0": + return text.getText(start, end) + offset = max(end, offset + 1) + + return string + + def presentContext(self): + if not self.isActive(): + return False + + try: + text = self._errorWidget.queryText() + except Exception: + return False + + string = text.getText(0, -1) + if not string: + return False + + msg = messages.MISSPELLED_WORD_CONTEXT % string + voice = self._script.speechGenerator.voice(string=msg) + self._script.speakMessage(msg, voice=voice) + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/__init__.py new file mode 100644 index 0000000..0d25fd0 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for xfwm4.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/script.py new file mode 100644 index 0000000..68f14e6 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/apps/xfwm4/script.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for xfwm4.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2011 The Cthulhu Team." +__license__ = "LGPL" + +import cthulhu.scripts.default as default +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +######################################################################## +# # +# The xfwm4 script class. # +# # +######################################################################## + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + + default.Script.__init__(self, app) + + def onTextInserted(self, event): + """Called whenever text is inserted into an object. Overridden + here so that we will speak each item as the user is switching + windows. + + Arguments: + - event: the Event + """ + + if not AXUtilities.is_label(event.source): + default.Script.onTextInserted(self, event) + return + + self.presentMessage(AXObject.get_name(event.source)) + + def onTextDeleted(self, event): + """Called whenever text is deleted from an object. Overridden + here because we wish to ignore text deletion events associated + with window switching. + + Arguments: + - event: the Event + """ + + if not AXUtilities.is_label(event.source): + default.Script.onTextDeleted(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/default.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/default.py new file mode 100644 index 0000000..86b3192 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/default.py @@ -0,0 +1,3455 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""The default Script for presenting information to the user using +both speech and Braille. This is based primarily on the de-facto +standard implementation of the AT-SPI, which is the GAIL support +for GTK.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010 Joanmarie Diggs" +__license__ = "LGPL" + +import gi +gi.require_version('Atspi', '2.0') +from gi.repository import Atspi + +import re +import time + +import cthulhu.braille as braille +import cthulhu.cmdnames as cmdnames +import cthulhu.dbus_service as dbus_service +import cthulhu.debug as debug +import cthulhu.find as find +import cthulhu.flat_review as flat_review +import cthulhu.input_event as input_event +import cthulhu.keybindings as keybindings +import cthulhu.messages as messages +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.phonnames as phonnames +import cthulhu.script as script +import cthulhu.script_manager as script_manager +import cthulhu.settings as settings +import cthulhu.settings_manager as settings_manager +import cthulhu.sound as sound +import cthulhu.speech as speech +import cthulhu.speechserver as speechserver +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_scriptManager = script_manager.getManager() +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# The Default script class. # +# # +######################################################################## + +class Script(script.Script): + + EMBEDDED_OBJECT_CHARACTER = '\ufffc' + NO_BREAK_SPACE_CHARACTER = '\u00a0' + + # generatorCache + # + DISPLAYED_LABEL = 'displayedLabel' + DISPLAYED_TEXT = 'displayedText' + KEY_BINDING = 'keyBinding' + NESTING_LEVEL = 'nestingLevel' + NODE_LEVEL = 'nodeLevel' + REAL_ACTIVE_DESCENDANT = 'realActiveDescendant' + + def __init__(self, app): + """Creates a new script for the given application. + + Arguments: + - app: the application to create a script for. + """ + script.Script.__init__(self, app) + + self.targetCursorCell = None + + self.justEnteredFlatReviewMode = False + + self.digits = '0123456789' + self.whitespace = ' \t\n\r\v\f' + + # A dictionary of non-standardly-named text attributes and their + # Atk equivalents. + # + self.attributeNamesDict = {} + + # Keep track of the last time we issued a mouse routing command + # so that we can guess if a change resulted from our moving the + # pointer. + # + self.lastMouseRoutingTime = None + + # The last location of the mouse, which we might want if routing + # the pointer elsewhere. + # + self.oldMouseCoordinates = [0, 0] + + self._lastWordCheckedForSpelling = "" + + self._inSayAll = False + self._sayAllIsInterrupted = False + self._sayAllContexts = [] + self.grab_ids = [] + + if app: + Atspi.Accessible.set_cache_mask( + app, Atspi.Cache.DEFAULT ^ Atspi.Cache.NAME ^ Atspi.Cache.DESCRIPTION) + + # Register D-Bus commands if available + try: + controller = dbus_service.get_remote_controller() + if controller: + tokens = ["DEFAULT: Registering D-Bus commands for default script"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + controller.register_decorated_module("DefaultScript", self) + except Exception as error: + tokens = ["DEFAULT: Exception registering D-Bus commands:", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings.""" + + self.inputEventHandlers["routePointerToItemHandler"] = \ + input_event.InputEventHandler( + Script.routePointerToItem, + cmdnames.ROUTE_POINTER_TO_ITEM) + + self.inputEventHandlers["leftClickReviewItemHandler"] = \ + input_event.InputEventHandler( + Script.leftClickReviewItem, + cmdnames.LEFT_CLICK_REVIEW_ITEM) + + self.inputEventHandlers["rightClickReviewItemHandler"] = \ + input_event.InputEventHandler( + Script.rightClickReviewItem, + cmdnames.RIGHT_CLICK_REVIEW_ITEM) + + self.inputEventHandlers["sayAllHandler"] = \ + input_event.InputEventHandler( + Script.sayAll, + cmdnames.SAY_ALL) + + self.inputEventHandlers["findHandler"] = \ + input_event.InputEventHandler( + cthulhu.showFindGUI, + cmdnames.SHOW_FIND_GUI) + + self.inputEventHandlers["findNextHandler"] = \ + input_event.InputEventHandler( + Script.findNext, + cmdnames.FIND_NEXT) + + self.inputEventHandlers["findPreviousHandler"] = \ + input_event.InputEventHandler( + Script.findPrevious, + cmdnames.FIND_PREVIOUS) + + self.inputEventHandlers["panBrailleLeftHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleLeft, + cmdnames.PAN_BRAILLE_LEFT, + False) # Do not enable learn mode for this action + + self.inputEventHandlers["panBrailleRightHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleRight, + cmdnames.PAN_BRAILLE_RIGHT, + False) # Do not enable learn mode for this action + + self.inputEventHandlers["goBrailleHomeHandler"] = \ + input_event.InputEventHandler( + Script.goBrailleHome, + cmdnames.GO_BRAILLE_HOME) + + self.inputEventHandlers["contractedBrailleHandler"] = \ + input_event.InputEventHandler( + Script.setContractedBraille, + cmdnames.SET_CONTRACTED_BRAILLE) + + self.inputEventHandlers["processRoutingKeyHandler"] = \ + input_event.InputEventHandler( + Script.processRoutingKey, + cmdnames.PROCESS_ROUTING_KEY) + + self.inputEventHandlers["processBrailleCutBeginHandler"] = \ + input_event.InputEventHandler( + Script.processBrailleCutBegin, + cmdnames.PROCESS_BRAILLE_CUT_BEGIN) + + self.inputEventHandlers["processBrailleCutLineHandler"] = \ + input_event.InputEventHandler( + Script.processBrailleCutLine, + cmdnames.PROCESS_BRAILLE_CUT_LINE) + + self.inputEventHandlers["toggleSleepModeHandler"] = \ + input_event.InputEventHandler( + Script.toggleSleepMode, + cmdnames.TOGGLE_SLEEP_MODE) + + self.inputEventHandlers["shutdownHandler"] = \ + input_event.InputEventHandler( + cthulhu.quitCthulhu, + cmdnames.QUIT_CTHULHU) + + self.inputEventHandlers["preferencesSettingsHandler"] = \ + input_event.InputEventHandler( + cthulhu.showPreferencesGUI, + cmdnames.SHOW_PREFERENCES_GUI) + + self.inputEventHandlers["appPreferencesSettingsHandler"] = \ + input_event.InputEventHandler( + cthulhu.showAppPreferencesGUI, + cmdnames.SHOW_APP_PREFERENCES_GUI) + + self.inputEventHandlers["cycleSettingsProfileHandler"] = \ + input_event.InputEventHandler( + Script.cycleSettingsProfile, + cmdnames.CYCLE_SETTINGS_PROFILE) + + self.inputEventHandlers["cycleDebugLevelHandler"] = \ + input_event.InputEventHandler( + Script.cycleDebugLevel, + cmdnames.CYCLE_DEBUG_LEVEL) + + self.inputEventHandlers["bypassNextCommandHandler"] = \ + input_event.InputEventHandler( + Script.bypassNextCommand, + cmdnames.BYPASS_NEXT_COMMAND) + + self.inputEventHandlers.update(self.notificationPresenter.get_handlers()) + self.inputEventHandlers.update(self.flatReviewPresenter.get_handlers()) + self.inputEventHandlers.update(self.speechAndVerbosityManager.get_handlers()) + self.inputEventHandlers.update(self.dateAndTimePresenter.get_handlers()) + self.inputEventHandlers.update(self.bookmarks.get_handlers()) + self.inputEventHandlers.update(self.objectNavigator.get_handlers()) + self.inputEventHandlers.update(self.whereAmIPresenter.get_handlers()) + self.inputEventHandlers.update(self.learnModePresenter.get_handlers()) + self.inputEventHandlers.update(self.mouseReviewer.get_handlers()) + self.inputEventHandlers.update(self.actionPresenter.get_handlers()) + cthulhu.getManager().getDynamicApiManager().registerAPI('inputEventHandlers',self.inputEventHandlers, overwrite=True) + cthulhu.getManager().getSignalManager().emitSignal('setup-inputeventhandlers-completed') + + def getInputEventHandlerKey(self, inputEventHandler): + """Returns the name of the key that contains an inputEventHadler + passed as argument + """ + + for keyName, handler in self.inputEventHandlers.items(): + if handler == inputEventHandler: + return keyName + + return None + + def getListeners(self): + """Sets up the AT-SPI event listeners for this script. + """ + listeners = script.Script.getListeners(self) + listeners["focus:"] = \ + self.onFocus + #listeners["keyboard:modifiers"] = \ + # self.noOp + listeners["document:reload"] = \ + self.onDocumentReload + listeners["document:load-complete"] = \ + self.onDocumentLoadComplete + listeners["document:load-stopped"] = \ + self.onDocumentLoadStopped + listeners["mouse:button"] = \ + self.onMouseButton + listeners["object:announcement"] = \ + self.onAnnouncement + listeners["object:property-change:accessible-name"] = \ + self.onNameChanged + listeners["object:property-change:accessible-description"] = \ + self.onDescriptionChanged + listeners["object:text-caret-moved"] = \ + self.onCaretMoved + listeners["object:text-changed:delete"] = \ + self.onTextDeleted + listeners["object:text-changed:insert"] = \ + self.onTextInserted + listeners["object:active-descendant-changed"] = \ + self.onActiveDescendantChanged + listeners["object:children-changed:add"] = \ + self.onChildrenAdded + listeners["object:children-changed:remove"] = \ + self.onChildrenRemoved + listeners["object:state-changed:active"] = \ + self.onActiveChanged + listeners["object:state-changed:busy"] = \ + self.onBusyChanged + listeners["object:state-changed:focused"] = \ + self.onFocusedChanged + listeners["object:state-changed:showing"] = \ + self.onShowingChanged + listeners["object:state-changed:checked"] = \ + self.onCheckedChanged + listeners["object:state-changed:pressed"] = \ + self.onPressedChanged + listeners["object:state-changed:indeterminate"] = \ + self.onIndeterminateChanged + listeners["object:state-changed:expanded"] = \ + self.onExpandedChanged + listeners["object:state-changed:selected"] = \ + self.onSelectedChanged + listeners["object:state-changed:sensitive"] = \ + self.onSensitiveChanged + listeners["object:text-attributes-changed"] = \ + self.onTextAttributesChanged + listeners["object:text-selection-changed"] = \ + self.onTextSelectionChanged + listeners["object:selection-changed"] = \ + self.onSelectionChanged + listeners["object:property-change:accessible-value"] = \ + self.onValueChanged + listeners["object:value-changed"] = \ + self.onValueChanged + listeners["object:column-reordered"] = \ + self.onColumnReordered + listeners["object:row-reordered"] = \ + self.onRowReordered + listeners["window:activate"] = \ + self.onWindowActivated + listeners["window:deactivate"] = \ + self.onWindowDeactivated + listeners["window:create"] = \ + self.onWindowCreated + listeners["window:destroy"] = \ + self.onWindowDestroyed + + return listeners + + def __getDesktopBindings(self): + """Returns an instance of keybindings.KeyBindings that use the + numeric keypad for focus tracking and flat review. + """ + + import cthulhu.desktop_keyboardmap as desktop_keyboardmap + keyBindings = keybindings.KeyBindings() + keyBindings.load(desktop_keyboardmap.keymap, self.inputEventHandlers) + return keyBindings + + def __getLaptopBindings(self): + """Returns an instance of keybindings.KeyBindings that use the + the main keyboard keys for focus tracking and flat review. + """ + + import cthulhu.laptop_keyboardmap as laptop_keyboardmap + keyBindings = keybindings.KeyBindings() + keyBindings.load(laptop_keyboardmap.keymap, self.inputEventHandlers) + return keyBindings + + def getExtensionBindings(self): + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"=== getExtensionBindings() called ===\n") + keyBindings = keybindings.KeyBindings() + + bindings = self.notificationPresenter.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + layout = _settingsManager.getSetting('keyboardLayout') + isDesktop = layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP + bindings = self.flatReviewPresenter.get_bindings(isDesktop) + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.whereAmIPresenter.get_bindings(isDesktop) + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.learnModePresenter.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.speechAndVerbosityManager.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.dateAndTimePresenter.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.objectNavigator.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.bookmarks.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.mouseReviewer.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.actionPresenter.get_bindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + # Add plugin keybindings from APIHelper storage + try: + import cthulhu.cthulhu as cthulhu + if hasattr(cthulhu, 'cthulhuApp') and cthulhu.cthulhuApp: + api_helper = cthulhu.cthulhuApp.getAPIHelper() + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"=== Checking for plugin bindings ===\n") + f.write(f"api_helper exists: {api_helper is not None}\n") + if api_helper: + f.write(f"api_helper has _gestureBindings: {hasattr(api_helper, '_gestureBindings')}\n") + if hasattr(api_helper, '_gestureBindings'): + f.write(f"_gestureBindings content: {api_helper._gestureBindings}\n") + f.write(f"Available contexts: {list(api_helper._gestureBindings.keys())}\n") + + if api_helper and hasattr(api_helper, '_gestureBindings'): + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"=== Adding plugin bindings in getExtensionBindings() ===\n") + + for context_name, context_bindings in api_helper._gestureBindings.items(): + for binding in context_bindings: + keyBindings.add(binding) + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"Added plugin binding: {binding.keysymstring} modifiers={binding.modifiers} desc={binding.handler.description}\n") + else: + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"=== No plugin bindings available ===\n") + else: + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"=== cthulhuApp not available ===\n") + except Exception as e: + import cthulhu.debug as debug + debug.printMessage(debug.LEVEL_WARNING, f"Failed to add plugin bindings: {e}", True) + with open('/tmp/extension_bindings_debug.log', 'a') as f: + f.write(f"Exception in plugin binding addition: {e}\n") + + return keyBindings + + def getKeyBindings(self): + """Defines the key bindings for this script. + + Returns an instance of keybindings.KeyBindings. + """ + + keyBindings = script.Script.getKeyBindings(self) + + bindings = self.getDefaultKeyBindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.getToolkitKeyBindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.getAppKeyBindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + bindings = self.getExtensionBindings() + for keyBinding in bindings.keyBindings: + keyBindings.add(keyBinding) + + try: + keyBindings = _settingsManager.overrideKeyBindings(self, keyBindings) + except Exception as error: + tokens = ["DEFAULT: Exception when overriding keybindings in", self, ":", error] + debug.printTokens(debug.LEVEL_WARNING, tokens, True) + + return keyBindings + + def getDefaultKeyBindings(self): + """Returns the default script's keybindings, i.e. without any of + the toolkit or application specific commands added.""" + + keyBindings = keybindings.KeyBindings() + + layout = _settingsManager.getSetting('keyboardLayout') + if layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP: + for keyBinding in self.__getDesktopBindings().keyBindings: + keyBindings.add(keyBinding) + else: + for keyBinding in self.__getLaptopBindings().keyBindings: + keyBindings.add(keyBinding) + + import cthulhu.common_keyboardmap as common_keyboardmap + keyBindings.load(common_keyboardmap.keymap, self.inputEventHandlers) + + return keyBindings + + def getBrailleBindings(self): + """Defines the braille bindings for this script. + + Returns a dictionary where the keys are BrlTTY commands and the + values are InputEventHandler instances. + """ + + msg = 'DEFAULT: Getting braille bindings.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + brailleBindings = script.Script.getBrailleBindings(self) + try: + brailleBindings[braille.brlapi.KEY_CMD_HWINLT] = \ + self.inputEventHandlers["panBrailleLeftHandler"] + brailleBindings[braille.brlapi.KEY_CMD_FWINLT] = \ + self.inputEventHandlers["panBrailleLeftHandler"] + brailleBindings[braille.brlapi.KEY_CMD_FWINLTSKIP] = \ + self.inputEventHandlers["panBrailleLeftHandler"] + brailleBindings[braille.brlapi.KEY_CMD_HWINRT] = \ + self.inputEventHandlers["panBrailleRightHandler"] + brailleBindings[braille.brlapi.KEY_CMD_FWINRT] = \ + self.inputEventHandlers["panBrailleRightHandler"] + brailleBindings[braille.brlapi.KEY_CMD_FWINRTSKIP] = \ + self.inputEventHandlers["panBrailleRightHandler"] + brailleBindings[braille.brlapi.KEY_CMD_HOME] = \ + self.inputEventHandlers["goBrailleHomeHandler"] + brailleBindings[braille.brlapi.KEY_CMD_SIXDOTS] = \ + self.inputEventHandlers["contractedBrailleHandler"] + brailleBindings[braille.brlapi.KEY_CMD_ROUTE] = \ + self.inputEventHandlers["processRoutingKeyHandler"] + brailleBindings[braille.brlapi.KEY_CMD_CUTBEGIN] = \ + self.inputEventHandlers["processBrailleCutBeginHandler"] + brailleBindings[braille.brlapi.KEY_CMD_CUTLINE] = \ + self.inputEventHandlers["processBrailleCutLineHandler"] + brailleBindings[braille.brlapi.KEY_CMD_HOME] = \ + self.inputEventHandlers["goBrailleHomeHandler"] + except AttributeError: + tokens = ["DEFAULT: Braille bindings unavailable in", self] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception as error: + tokens = ["DEFAULT: Exception getting braille bindings in", self, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + reviewBindings = self.flatReviewPresenter.get_braille_bindings() + brailleBindings.update(reviewBindings) + + msg = 'DEFAULT: Finished getting braille bindings.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + return brailleBindings + + def deactivate(self): + """Called when this script is deactivated.""" + + self._inSayAll = False + self._sayAllIsInterrupted = False + self.pointOfReference = {} + + self.removeKeyGrabs() + + def getEnabledKeyBindings(self): + """ Returns the key bindings that are currently active. """ + return self.getKeyBindings().getBoundBindings() + + def addKeyGrabs(self): + """ Sets up the key grabs currently needed by this script. """ + if cthulhu_state.device is None: + return + msg = "DEFAULT: adding key grabs" + debug.printMessage(debug.LEVEL_INFO, msg, True) + bound = self.getEnabledKeyBindings() + for b in bound: + for id in cthulhu.addKeyGrab(b): + self.grab_ids.append(id) + + def removeKeyGrabs(self): + """ Removes this script's AT-SPI key grabs. """ + msg = "DEFAULT: removing key grabs" + debug.printMessage(debug.LEVEL_INFO, msg, True) + for id in self.grab_ids: + cthulhu.removeKeyGrab(id) + self.grab_ids = [] + + def refreshKeyGrabs(self): + """ Refreshes the enabled key grabs for this script. """ + # TODO: Should probably avoid removing key grabs and re-adding them. + # Otherwise, a key could conceivably leak through while the script is + # in the process of updating the bindings. + self.removeKeyGrabs() + self.addKeyGrabs() + + def registerEventListeners(self): + super().registerEventListeners() + self.utilities.connectToClipboard() + + def deregisterEventListeners(self): + super().deregisterEventListeners() + self.utilities.disconnectFromClipboard() + + def _saveFocusedObjectInfo(self, obj): + """Saves some basic information about obj. Note that this method is + intended to be called primarily (if not only) by locusOfFocusChanged(). + It is expected that accessible event callbacks will update the point + of reference data specific to that event. The goal here is to weed + out duplicate events.""" + + if not obj: + return + + # We want to save the name because some apps and toolkits emit name + # changes after the focus or selection has changed, even though the + # name has not. + name = AXObject.get_name(obj) + names = self.pointOfReference.get('names', {}) + names[hash(obj)] = name + if cthulhu_state.activeWindow: + names[hash(cthulhu_state.activeWindow)] = AXObject.get_name(cthulhu_state.activeWindow) + self.pointOfReference['names'] = names + + descriptions = self.pointOfReference.get('descriptions', {}) + descriptions[hash(obj)] = AXObject.get_description(obj) + self.pointOfReference['descriptions'] = descriptions + + # We want to save the offset for text objects because some apps and + # toolkits emit caret-moved events immediately after a text object + # gains focus, even though the caret has not actually moved. + try: + text = obj.queryText() + caretOffset = text.caretOffset + except Exception: + pass + else: + self._saveLastCursorPosition(obj, max(0, caretOffset)) + self.utilities.updateCachedTextSelection(obj) + + # We want to save the current row and column of a newly focused + # or selected table cell so that on subsequent cell focus/selection + # we only present the changed location. + row, column = self.utilities.coordinatesForCell(obj, findCellAncestor=True) + self.pointOfReference['lastColumn'] = column + self.pointOfReference['lastRow'] = row + + self.pointOfReference['checkedChange'] = hash(obj), AXUtilities.is_checked(obj) + self.pointOfReference['selectedChange'] = hash(obj), AXUtilities.is_selected(obj) + self.pointOfReference['expandedChange'] = hash(obj), AXUtilities.is_expanded(obj) + + def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): + """Called when the visual object with focus changes. + + Arguments: + - event: if not None, the Event that caused the change + - oldLocusOfFocus: Accessible that is the old locus of focus + - newLocusOfFocus: Accessible that is the new locus of focus + """ + + self.utilities.presentFocusChangeReason() + + if not newLocusOfFocus: + cthulhu_state.noFocusTimeStamp = time.time() + return + + if AXUtilities.is_defunct(newLocusOfFocus): + return + + if oldLocusOfFocus == newLocusOfFocus: + msg = 'DEFAULT: old focus == new focus' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + # Don't apply the is-same-object heuristic in the case of table cells. + # One scenario is email client message lists. When you delete a message + # and land on the next one, the cells likely occupy the same space, + # have the same role, and might even have the same name, same path, etc. + if not AXUtilities.is_table_cell(oldLocusOfFocus) \ + and not AXUtilities.is_table_cell(newLocusOfFocus) \ + and self.utilities.isSameObject(oldLocusOfFocus, newLocusOfFocus): + tokens = ["DEFAULT: old focus", oldLocusOfFocus, + "believed to be same as new focus", newLocusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + try: + if self.findCommandRun: + # Then the Cthulhu Find dialog has just given up focus + # to the original window. We don't want to speak + # the window title, current line, etc. + return + except Exception: + pass + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.quit() + + if self.learnModePresenter.is_active(): + self.learnModePresenter.quit() + + topLevel = self.utilities.topLevelObject(newLocusOfFocus) + if cthulhu_state.activeWindow != topLevel: + cthulhu.setActiveWindow(topLevel) + + self.updateBraille(newLocusOfFocus) + + utterances = self.speechGenerator.generateSpeech( + newLocusOfFocus, + priorObj=oldLocusOfFocus) + + if self.utilities.shouldInterruptForLocusOfFocusChange( + oldLocusOfFocus, newLocusOfFocus, event): + self.presentationInterrupt() + speech.speak(utterances, interrupt=False) + cthulhu.emitRegionChanged(newLocusOfFocus) + self._saveFocusedObjectInfo(newLocusOfFocus) + + def activate(self): + """Called when this script is activated.""" + + tokens = ["DEFAULT: Activating script for", self.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + _settingsManager.loadAppSettings(self) + braille.checkBrailleSetting() + braille.setupKeyRanges(self.brailleBindings.keys()) + speech.checkSpeechSetting() + self.speechAndVerbosityManager.update_punctuation_level() + self.speechAndVerbosityManager.update_capitalization_style() + + # Use new InputEventManager for global keyboard capture by default + # Only fall back to legacy handling for problematic applications + cthulhu.setKeyHandling(True) + + self.addKeyGrabs() + + tokens = ["DEFAULT: Script for", self.app, "activated"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def updateBraille(self, obj, **args): + """Updates the braille display to show the give object. + + Arguments: + - obj: the Accessible + """ + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: update disabled", True) + return + + if not obj: + return + + result, focusedRegion = self.brailleGenerator.generateBraille(obj, **args) + if not result: + return + + self.clearBraille() + line = self.getNewBrailleLine() + braille.addLine(line) + self.addBrailleRegionsToLine(result, line) + + extraRegion = args.get('extraRegion') + if extraRegion: + self.addBrailleRegionToLine(extraRegion, line) + self.setBrailleFocus(extraRegion) + else: + self.setBrailleFocus(focusedRegion) + + self.refreshBraille(True) + + ######################################################################## + # # + # INPUT EVENT HANDLERS (AKA CTHULHU COMMANDS) # + # # + ######################################################################## + + def toggleSleepMode(self, input_event=None): + """Toggles between sleep mode and regular mode.""" + script_manager = _scriptManager + debug.printMessage(debug.LEVEL_INFO, f"SLEEP: Attempting to create sleepmode script for app: {self.app}", True) + sleepScript = script_manager._newNamedScript(self.app, "sleepmode") + debug.printMessage(debug.LEVEL_INFO, f"SLEEP: Result of _newNamedScript: {sleepScript}", True) + if sleepScript: + script_manager.setActiveScript(sleepScript, "Sleep mode toggled") + else: + self.presentMessage("Could not activate sleep mode") + return True + + def bypassNextCommand(self, inputEvent=None): + """Causes the next keyboard command to be ignored by Cthulhu + and passed along to the current application. + + Returns True to indicate the input event has been consumed. + """ + + self.presentMessage(messages.BYPASS_MODE_ENABLED) + cthulhu_state.bypassNextCommand = True + self.removeKeyGrabs() + return True + + def findNext(self, inputEvent): + """Searches forward for the next instance of the string + searched for via the Cthulhu Find dialog. Other than direction + and the starting point, the search options initially specified + (case sensitivity, window wrap, and full/partial match) are + preserved. + """ + + lastQuery = find.getLastQuery() + if lastQuery: + lastQuery.searchBackwards = False + lastQuery.startAtTop = False + self.find(lastQuery) + else: + cthulhu.showFindGUI() + + def findPrevious(self, inputEvent): + """Searches backwards for the next instance of the string + searched for via the Cthulhu Find dialog. Other than direction + and the starting point, the search options initially specified + (case sensitivity, window wrap, and full/or partial match) are + preserved. + """ + + lastQuery = find.getLastQuery() + if lastQuery: + lastQuery.searchBackwards = True + lastQuery.startAtTop = False + self.find(lastQuery) + else: + cthulhu.showFindGUI() + + def panBrailleLeft(self, inputEvent=None, panAmount=0): + """Pans the braille display to the left. If panAmount is non-zero, + the display is panned by that many cells. If it is 0, the display + is panned one full display width. In flat review mode, panning + beyond the beginning will take you to the end of the previous line. + + In focus tracking mode, the cursor stays at its logical position. + In flat review mode, the review cursor moves to character + associated with cell 0.""" + + if isinstance(inputEvent, input_event.KeyboardEvent) \ + and not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + msg = "DEFAULT: panBrailleLeft command requires braille or braille monitor" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.flatReviewPresenter.is_active(): + if self.isBrailleBeginningShowing(): + self.flatReviewPresenter.go_start_of_line(self, inputEvent) + self.flatReviewPresenter.go_previous_character(self, inputEvent) + else: + self.panBrailleInDirection(panAmount, panToLeft=True) + + self._setFlatReviewContextToBeginningOfBrailleDisplay() + self.targetCursorCell = 1 + self.updateBrailleReview(self.targetCursorCell) + elif self.isBrailleBeginningShowing() and cthulhu_state.locusOfFocus \ + and self.utilities.isTextArea(cthulhu_state.locusOfFocus): + + # If we're at the beginning of a line of a multiline text + # area, then force it's caret to the end of the previous + # line. The assumption here is that we're currently + # viewing the line that has the caret -- which is a pretty + # good assumption for focus tacking mode. When we set the + # caret position, we will get a caret event, which will + # then update the braille. + # + text = cthulhu_state.locusOfFocus.queryText() + [lineString, startOffset, endOffset] = text.getTextAtOffset( + text.caretOffset, + Atspi.TextBoundaryType.LINE_START) + movedCaret = False + if startOffset > 0: + movedCaret = text.setCaretOffset(startOffset - 1) + + # If we didn't move the caret and we're in a terminal, we + # jump into flat review to review the text. See + # http://bugzilla.gnome.org/show_bug.cgi?id=482294. + # + if not movedCaret and AXUtilities.is_terminal(cthulhu_state.locusOfFocus): + context = self.getFlatReviewContext() + context.goBegin(flat_review.Context.LINE) + self.flatReviewPresenter.go_previous_character(self, inputEvent) + else: + self.panBrailleInDirection(panAmount, panToLeft=True) + # We might be panning through a flashed message. + # + braille.resetFlashTimer() + self.refreshBraille(False, stopFlash=False) + + return True + + def panBrailleLeftOneChar(self, inputEvent=None): + """Nudges the braille display one character to the left. + + In focus tracking mode, the cursor stays at its logical position. + In flat review mode, the review cursor moves to character + associated with cell 0.""" + + self.panBrailleLeft(inputEvent, 1) + + def panBrailleRight(self, inputEvent=None, panAmount=0): + """Pans the braille display to the right. If panAmount is non-zero, + the display is panned by that many cells. If it is 0, the display + is panned one full display width. In flat review mode, panning + beyond the end will take you to the beginning of the next line. + + In focus tracking mode, the cursor stays at its logical position. + In flat review mode, the review cursor moves to character + associated with cell 0.""" + + if isinstance(inputEvent, input_event.KeyboardEvent) \ + and not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + msg = "DEFAULT: panBrailleRight command requires braille or braille monitor" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.flatReviewPresenter.is_active(): + if self.isBrailleEndShowing(): + self.flatReviewPresenter.go_end_of_line(self, inputEvent) + # Reviewing the next character also updates the braille output + # and refreshes the display. + self.flatReviewPresenter.go_next_character(self, inputEvent) + return + self.panBrailleInDirection(panAmount, panToLeft=False) + self._setFlatReviewContextToBeginningOfBrailleDisplay() + self.targetCursorCell = 1 + self.updateBrailleReview(self.targetCursorCell) + elif self.isBrailleEndShowing() and cthulhu_state.locusOfFocus \ + and self.utilities.isTextArea(cthulhu_state.locusOfFocus): + # If we're at the end of a line of a multiline text area, then + # force it's caret to the beginning of the next line. The + # assumption here is that we're currently viewing the line that + # has the caret -- which is a pretty good assumption for focus + # tacking mode. When we set the caret position, we will get a + # caret event, which will then update the braille. + # + text = cthulhu_state.locusOfFocus.queryText() + [lineString, startOffset, endOffset] = text.getTextAtOffset( + text.caretOffset, + Atspi.TextBoundaryType.LINE_START) + if endOffset < text.characterCount: + text.setCaretOffset(endOffset) + else: + self.panBrailleInDirection(panAmount, panToLeft=False) + # We might be panning through a flashed message. + # + braille.resetFlashTimer() + self.refreshBraille(False, stopFlash=False) + + return True + + def panBrailleRightOneChar(self, inputEvent=None): + """Nudges the braille display one character to the right. + + In focus tracking mode, the cursor stays at its logical position. + In flat review mode, the review cursor moves to character + associated with cell 0.""" + + self.panBrailleRight(inputEvent, 1) + + def goBrailleHome(self, inputEvent=None): + """Returns to the component with focus.""" + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.quit() + return True + + return braille.returnToRegionWithFocus(inputEvent) + + def setContractedBraille(self, inputEvent=None): + """Toggles contracted braille.""" + + self._setContractedBraille(inputEvent) + return True + + def processRoutingKey(self, inputEvent=None): + """Processes a cursor routing key.""" + + braille.processRoutingKey(inputEvent) + return True + + def processBrailleCutBegin(self, inputEvent=None): + """Clears the selection and moves the caret offset in the currently + active text area. + """ + + obj, caretOffset = self.getBrailleCaretContext(inputEvent) + + if caretOffset >= 0: + self.utilities.clearTextSelection(obj) + self.utilities.setCaretOffset(obj, caretOffset) + + return True + + def processBrailleCutLine(self, inputEvent=None): + """Extends the text selection in the currently active text + area and also copies the selected text to the system clipboard.""" + + obj, caretOffset = self.getBrailleCaretContext(inputEvent) + + if caretOffset >= 0: + self.utilities.adjustTextSelection(obj, caretOffset) + texti = obj.queryText() + startOffset, endOffset = texti.getSelection(0) + self.utilities.setClipboardText(texti.getText(startOffset, endOffset)) + + return True + + def routePointerToItem(self, inputEvent=None): + """Moves the mouse pointer to the current item.""" + + # Store the original location for scripts which want to restore + # it later. + # + self.oldMouseCoordinates = self.utilities.absoluteMouseCoordinates() + self.lastMouseRoutingTime = time.time() + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.route_pointer_to_object(self, inputEvent) + return True + + if self.eventSynthesizer.route_to_character(cthulhu_state.locusOfFocus) \ + or self.eventSynthesizer.route_to_object(cthulhu_state.locusOfFocus): + self.presentMessage(messages.MOUSE_MOVED_SUCCESS) + return True + + full = messages.LOCATION_NOT_FOUND_FULL + brief = messages.LOCATION_NOT_FOUND_BRIEF + self.presentMessage(full, brief) + return False + + def leftClickReviewItem(self, inputEvent=None): + """Performs a left mouse button click on the current item.""" + + if self.flatReviewPresenter.is_active(): + obj = self.flatReviewPresenter.get_current_object(self, inputEvent) + if self.eventSynthesizer.try_all_clickable_actions(obj): + return True + return self.flatReviewPresenter.left_click_on_object(self, inputEvent) + + if self.eventSynthesizer.try_all_clickable_actions(cthulhu_state.locusOfFocus): + return True + + if self.utilities.queryNonEmptyText(cthulhu_state.locusOfFocus): + if self.eventSynthesizer.click_character(cthulhu_state.locusOfFocus, 1): + return True + + if self.eventSynthesizer.click_object(cthulhu_state.locusOfFocus, 1): + return True + + full = messages.LOCATION_NOT_FOUND_FULL + brief = messages.LOCATION_NOT_FOUND_BRIEF + self.presentMessage(full, brief) + return False + + def rightClickReviewItem(self, inputEvent=None): + """Performs a right mouse button click on the current item.""" + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.right_click_on_object(self, inputEvent) + return True + + if self.eventSynthesizer.click_character(cthulhu_state.locusOfFocus, 3): + return True + + if self.eventSynthesizer.click_object(cthulhu_state.locusOfFocus, 3): + return True + + full = messages.LOCATION_NOT_FOUND_FULL + brief = messages.LOCATION_NOT_FOUND_BRIEF + self.presentMessage(full, brief) + return False + + def spellCurrentItem(self, itemString): + """Spell the current flat review word or line. + + Arguments: + - itemString: the string to spell. + """ + + for character in itemString: + self.speakCharacter(character) + + @dbus_service.command + def sayAll(self, inputEvent, obj=None, offset=None, notify_user=True): + """Speaks the entire document or text, starting from the current position.""" + obj = obj or cthulhu_state.locusOfFocus + if not obj or AXObject.is_dead(obj): + self.presentMessage(messages.LOCATION_NOT_FOUND_FULL) + return True + + try: + text = obj.queryText() + except NotImplementedError: + utterances = self.speechGenerator.generateSpeech(obj) + utterances.extend(self.tutorialGenerator.getTutorial(obj, False)) + speech.speak(utterances) + except AttributeError: + pass + else: + if offset is None: + offset = text.caretOffset + speech.sayAll(self.textLines(obj, offset), + self.__sayAllProgressCallback) + + return True + + def cycleSettingsProfile(self, inputEvent=None): + """Cycle through the user's existing settings profiles.""" + + profiles = _settingsManager.availableProfiles() + if not (profiles and profiles[0]): + self.presentMessage(messages.PROFILE_NOT_FOUND) + return True + + def isMatch(x): + return x is not None and x[1] == _settingsManager.getProfile() + + current = list(filter(isMatch, profiles))[0] + try: + name, profileID = profiles[profiles.index(current) + 1] + except IndexError: + name, profileID = profiles[0] + + _settingsManager.setProfile(profileID, updateLocale=True) + + braille.checkBrailleSetting() + + speech.shutdown() + speech.init() + + # TODO: This is another "too close to code freeze" hack to cause the + # command names to be presented in the correct language. + self.setupInputEventHandlers() + + self.presentMessage(messages.PROFILE_CHANGED % name, name) + return True + + def cycleDebugLevel(self, inputEvent=None): + levels = [debug.LEVEL_ALL, "all", + debug.LEVEL_FINEST, "finest", + debug.LEVEL_FINER, "finer", + debug.LEVEL_FINE, "fine", + debug.LEVEL_CONFIGURATION, "configuration", + debug.LEVEL_INFO, "info", + debug.LEVEL_WARNING, "warning", + debug.LEVEL_SEVERE, "severe", + debug.LEVEL_OFF, "off"] + + try: + levelIndex = levels.index(debug.debugLevel) + 2 + except Exception: + levelIndex = 0 + else: + if levelIndex >= len(levels): + levelIndex = 0 + + debug.debugLevel = levels[levelIndex] + briefMessage = levels[levelIndex + 1] + fullMessage = f"Debug level {briefMessage}." + self.presentMessage(fullMessage, briefMessage) + + return True + + ######################################################################## + # # + # AT-SPI OBJECT EVENT HANDLERS # + # # + ######################################################################## + + def noOp(self, event): + """Just here to capture events. + + Arguments: + - event: the Event + """ + pass + + def onActiveChanged(self, event): + """Callback for object:state-changed:active accessibility events.""" + + window = event.source + if AXUtilities.is_application(AXObject.get_parent(event.source)): + window = AXObject.find_real_app_and_window_for(event.source)[1] + + if AXUtilities.is_dialog_or_alert(window) or AXUtilities.is_frame(window): + if event.detail1 and not self.utilities.canBeActiveWindow(window): + return + + sourceIsActiveWindow = self.utilities.isSameObject(window, cthulhu_state.activeWindow) + if sourceIsActiveWindow and not event.detail1: + if self.utilities.inMenu(): + msg = "DEFAULT: Ignoring event. In menu." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not self.utilities.eventIsUserTriggered(event): + msg = "DEFAULT: Not clearing state. Event is not user triggered." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "DEFAULT: Event is for active window. Clearing state." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setActiveWindow(None) + return + + if not sourceIsActiveWindow and event.detail1: + msg = "DEFAULT: Updating active window." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setActiveWindow(window, alsoSetLocusOfFocus=True, notifyScript=True) + + if self.findCommandRun: + self.findCommandRun = False + self.find() + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if not event.any_data: + msg = "DEFAULT: Ignoring event. No any_data." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not AXUtilities.is_focused(event.source) \ + and not AXUtilities.is_focused(event.any_data): + msg = "DEFAULT: Ignoring event. Neither source nor child have focused state." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.stopSpeechOnActiveDescendantChanged(event): + self.presentationInterrupt() + + tokens = ["DEFAULT: Setting locus of focus to any_data", event.any_data] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, event.any_data) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + pass + + def onCheckedChanged(self, event): + """Callback for object:state-changed:checked accessibility events.""" + + if not self.utilities.isSameObject(event.source, cthulhu_state.locusOfFocus): + return + + if AXUtilities.is_expandable(event.source): + return + + # Radio buttons normally change their state when you arrow to them, + # so we handle the announcement of their state changes in the focus + # handling code. However, we do need to handle radio buttons where + # the user needs to press the space key to select them. + if AXObject.get_role(event.source) == Atspi.Role.RADIO_BUTTON: + eventString, mods = self.utilities.lastKeyAndModifiers() + if eventString not in [" ", "space"]: + return + + oldObj, oldState = self.pointOfReference.get('checkedChange', (None, 0)) + if hash(oldObj) == hash(event.source) and oldState == event.detail1: + return + + self.presentObject(event.source, alreadyFocused=True, interrupt=True) + self.pointOfReference['checkedChange'] = hash(event.source), event.detail1 + + def onChildrenAdded(self, event): + """Callback for object:children-changed:add accessibility events.""" + + AXObject.clear_cache_now("children-changed event.") + + def onChildrenRemoved(self, event): + """Callback for object:children-changed:remove accessibility events.""" + + AXObject.clear_cache_now("children-changed event.") + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + obj, offset = self.pointOfReference.get("lastCursorPosition", (None, -1)) + if offset == event.detail1 and obj == event.source: + msg = "DEFAULT: Event is for last saved cursor position" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not AXUtilities.is_showing(event.source): + msg = "DEFAULT: Event source is not showing. Clearing cache." + debug.printMessage(debug.LEVEL_INFO, msg, True) + AXObject.clear_cache(obj) + if not AXUtilities.is_showing(event.source): + msg = "DEFAULT: Event source is still not showing." + debug.printMessage(debug.LEVEL_INFO, msg, True) + if not self.utilities.presentEventFromNonShowingObject(event): + return + + if event.source != cthulhu_state.locusOfFocus and AXUtilities.is_focused(event.source): + topLevelObject = self.utilities.topLevelObject(event.source) + if self.utilities.isSameObject(cthulhu_state.activeWindow, topLevelObject): + tokens = ["DEFAULT: Updating locusOfFocus from", cthulhu_state.locusOfFocus, + "to", event.source] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, event.source, False) + else: + tokens = ["DEFAULT: Source window (", topLevelObject, ") is not active window (", + cthulhu_state.activeWindow] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if event.source != cthulhu_state.locusOfFocus: + tokens = ["DEFAULT: Event source (", event.source, ") is not locusOfFocus (", + cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.quit() + + text = event.source.queryText() + try: + text.caretOffset + except Exception as error: + tokens = ["DEFAULT: Exception getting caretOffset for", event.source, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + self._saveLastCursorPosition(event.source, text.caretOffset) + if text.getNSelections() > 0: + msg = "DEFAULT: Event source has text selections" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.handleTextSelectionChange(event.source) + return + else: + start, end, string = self.utilities.getCachedTextSelection(obj) + if string and self.utilities.handleTextSelectionChange(obj): + msg = "DEFAULT: Event handled as text selection change" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "DEFAULT: Presenting text at new caret position" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._presentTextAtNewCaretPosition(event) + + def onDescriptionChanged(self, event): + """Callback for object:property-change:accessible-description events.""" + + obj = event.source + descriptions = self.pointOfReference.get('description', {}) + oldDescription = descriptions.get(hash(obj)) + if oldDescription == event.any_data: + tokens = ["DEFAULT: Old description (", oldDescription, ") is the same as new one"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if obj != cthulhu_state.locusOfFocus: + msg = "DEFAULT: Event is for object other than the locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + descriptions[hash(obj)] = event.any_data + self.pointOfReference['descriptions'] = descriptions + if event.any_data: + self.presentMessage(event.any_data) + + def onDocumentReload(self, event): + """Callback for document:reload accessibility events.""" + + pass + + def onDocumentLoadComplete(self, event): + """Callback for document:load-complete accessibility events.""" + + pass + + def onDocumentLoadStopped(self, event): + """Callback for document:load-stopped accessibility events.""" + + pass + + def onExpandedChanged(self, event): + """Callback for object:state-changed:expanded accessibility events.""" + + if not self.utilities.isPresentableExpandedChangedEvent(event): + return + + obj = event.source + oldObj, oldState = self.pointOfReference.get('expandedChange', (None, 0)) + if hash(oldObj) == hash(obj) and oldState == event.detail1: + return + + self.presentObject(obj, alreadyFocused=True, interrupt=True) + self.pointOfReference['expandedChange'] = hash(obj), event.detail1 + + details = self.utilities.detailsContentForObject(obj) + for detail in details: + self.speakMessage(detail, interrupt=False) + + def onIndeterminateChanged(self, event): + """Callback for object:state-changed:indeterminate accessibility events.""" + + # If this state is cleared, the new state will become checked or unchecked + # and we should get object:state-changed:checked events for those cases. + # Therefore, if the state is not now indeterminate/partially checked, + # ignore this event. + if not event.detail1: + return + + obj = event.source + if not self.utilities.isSameObject(obj, cthulhu_state.locusOfFocus): + return + + oldObj, oldState = self.pointOfReference.get('indeterminateChange', (None, 0)) + if hash(oldObj) == hash(obj) and oldState == event.detail1: + return + + self.presentObject(obj, alreadyFocused=True, interrupt=True) + self.pointOfReference['indeterminateChange'] = hash(obj), event.detail1 + + def onMouseButton(self, event): + """Callback for mouse:button events.""" + + mouseEvent = input_event.MouseButtonEvent(event) + cthulhu_state.lastInputEvent = mouseEvent + if not mouseEvent.pressed: + return + + windowChanged = cthulhu_state.activeWindow != mouseEvent.window + if windowChanged: + cthulhu.setActiveWindow(mouseEvent.window, alsoSetLocusOfFocus=True) + + self.presentationInterrupt() + if AXUtilities.is_focused(mouseEvent.obj): + cthulhu.setLocusOfFocus(None, mouseEvent.obj, windowChanged) + + def onAnnouncement(self, event): + """Callback for object:announcement events.""" + + if isinstance(event.any_data, str): + self.presentMessage(event.any_data) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + names = self.pointOfReference.get('names', {}) + oldName = names.get(hash(event.source)) + if oldName == event.any_data: + tokens = ["DEFAULT: Old name (", oldName, ") is the same as new name"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if AXUtilities.is_combo_box(event.source) or AXUtilities.is_table_cell(event.source): + msg = "DEFAULT: Event is redundant notification for this role" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if AXUtilities.is_frame(event.source): + if event.source != cthulhu_state.activeWindow: + msg = "DEFAULT: Event is for frame other than the active window" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + elif event.source != cthulhu_state.locusOfFocus: + msg = "DEFAULT: Event is for object other than the locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + names[hash(event.source)] = event.any_data + self.pointOfReference['names'] = names + if event.any_data: + self.presentMessage(event.any_data) + + def onPressedChanged(self, event): + """Callback for object:state-changed:pressed accessibility events.""" + + obj = event.source + if not self.utilities.isSameObject(obj, cthulhu_state.locusOfFocus): + return + + oldObj, oldState = self.pointOfReference.get('pressedChange', (None, 0)) + if hash(oldObj) == hash(obj) and oldState == event.detail1: + return + + self.presentObject(obj, alreadyFocused=True, interrupt=True) + self.pointOfReference['pressedChange'] = hash(obj), event.detail1 + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + AXObject.clear_cache(event.source) + if not AXUtilities.is_focused(event.source): + msg = "DEFAULT: Event is not toggling of currently-focused object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not self.utilities.isSameObject(cthulhu_state.locusOfFocus, event.source): + tokens = ["DEFAULT: Event is not for locusOfFocus", cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return + + isSelected = AXUtilities.is_selected(event.source) + if isSelected != event.detail1: + msg = "DEFAULT: Bogus event: detail1 doesn't match state" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + oldObj, oldState = self.pointOfReference.get('selectedChange', (None, 0)) + if hash(oldObj) == hash(event.source) and oldState == event.detail1: + msg = "DEFAULT: Duplicate or spam event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + announceState = False + keyString, mods = self.utilities.lastKeyAndModifiers() + if keyString == "space": + announceState = True + elif keyString in ["Down", "Up"] and AXUtilities.is_table_cell(event.source): + announceState = isSelected + + if not announceState: + return + + # TODO - JD: Unlike the other state-changed callbacks, it seems unwise + # to call generateSpeech() here because that also will present the + # expandable state if appropriate for the object type. The generators + # need to gain some smarts w.r.t. state changes. + + if event.detail1: + self.speakMessage(messages.TEXT_SELECTED, interrupt=False) + else: + self.speakMessage(messages.TEXT_UNSELECTED, interrupt=False) + + self.pointOfReference['selectedChange'] = hash(event.source), event.detail1 + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if self.utilities.handlePasteLocusOfFocusChange(): + if self.utilities.topLevelObjectIsActiveAndCurrent(event.source): + cthulhu.setLocusOfFocus(event, event.source, False) + elif self.utilities.handleContainerSelectionChange(event.source): + return + elif AXUtilities.manages_descendants(event.source): + return + + # If the current item's selection is toggled, we'll present that + # via the state-changed event. + keyString, mods = self.utilities.lastKeyAndModifiers() + if keyString == "space": + return + + if AXUtilities.is_combo_box(event.source) and not AXUtilities.is_expanded(event.source): + if AXUtilities.is_focused(self.utilities.getEntryForEditableComboBox(event.source)): + return + elif AXUtilities.is_page_tab_list(event.source) and self.flatReviewPresenter.is_active(): + # If a wizard-like notebook page being reviewed changes, we might not get + # any events to update the locusOfFocus. As a result, subsequent flat + # review commands will continue to present the stale content. + # TODO - JD: We can potentially do some automatic reading here. + self.flatReviewPresenter.quit() + + mouseReviewItem = self.mouseReviewer.getCurrentItem() + selectedChildren = self.utilities.selectedChildren(event.source) + for child in selectedChildren: + if AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == child): + tokens = ["DEFAULT: Child", child, "is ancestor of locusOfFocus"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._saveFocusedObjectInfo(cthulhu_state.locusOfFocus) + return + + if child == mouseReviewItem: + tokens = ["DEFAULT: Child", child, "is current mouse review item"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + continue + + if AXUtilities.is_page_tab(child) and cthulhu_state.locusOfFocus \ + and AXObject.get_name(child) == AXObject.get_name(cthulhu_state.locusOfFocus) \ + and not AXUtilities.is_focused(event.source): + tokens = ["DEFAULT:", child, "'s selection redundant to", cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + break + + if not self.utilities.isLayoutOnly(child): + cthulhu.setLocusOfFocus(event, child) + break + + def onSensitiveChanged(self, event): + """Callback for object:state-changed:sensitive accessibility events.""" + pass + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + pass + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + return + + if not AXUtilities.is_focused(event.source): + return + + obj = event.source + window, dialog = self.utilities.frameAndDialog(obj) + clearCache = window != cthulhu_state.activeWindow + if window and not self.utilities.canBeActiveWindow(window, clearCache) and not dialog: + return + + if AXObject.get_child_count(obj) and not AXUtilities.is_combo_box(obj): + selectedChildren = self.utilities.selectedChildren(obj) + if selectedChildren: + obj = selectedChildren[0] + + cthulhu.setLocusOfFocus(event, obj) + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + obj = event.source + role = AXObject.get_role(obj) + if role == Atspi.Role.NOTIFICATION: + if not event.detail1: + return + + speech.speak(self.speechGenerator.generateSpeech(obj)) + msg = self.utilities.getNotificationContent(obj) + self.displayBrailleMessage(msg, flashTime=settings.brailleFlashTime) + self.notificationPresenter.save_notification(msg) + return + + if role == Atspi.Role.TOOL_TIP: + keyString, mods = self.utilities.lastKeyAndModifiers() + if keyString != "F1" \ + and not _settingsManager.getSetting('presentToolTips'): + return + if event.detail1: + self.presentObject(obj, interrupt=True) + return + + if cthulhu_state.locusOfFocus and keyString == "F1": + obj = cthulhu_state.locusOfFocus + self.presentObject(obj, priorObj=event.source, interrupt=True) + return + + def onTextAttributesChanged(self, event): + """Callback for object:text-attributes-changed accessibility events.""" + + if not self.utilities.isPresentableTextChangedEventForLocusOfFocus(event): + return + + text = self.utilities.queryNonEmptyText(event.source) + if not text: + msg = "DEFAULT: Querying non-empty text returned None" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if _settingsManager.getSetting('speakMisspelledIndicator'): + offset = text.caretOffset + if not text.getText(offset, offset+1).isalnum(): + offset -= 1 + if self.utilities.isWordMisspelled(event.source, offset-1) \ + or self.utilities.isWordMisspelled(event.source, offset+1): + self.speakMessage(messages.MISSPELLED) + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if not self.utilities.isPresentableTextChangedEventForLocusOfFocus(event): + return + + self.utilities.handleUndoTextEvent(event) + + cthulhu.setLocusOfFocus(event, event.source, False) + self.updateBraille(event.source) + + full, brief = "", "" + if self.utilities.isClipboardTextChangedEvent(event): + msg = "DEFAULT: Deletion is believed to be due to clipboard cut" + debug.printMessage(debug.LEVEL_INFO, msg, True) + full, brief = messages.CLIPBOARD_CUT_FULL, messages.CLIPBOARD_CUT_BRIEF + elif self.utilities.isSelectedTextDeletionEvent(event): + msg = "DEFAULT: Deletion is believed to be due to deleting selected text" + debug.printMessage(debug.LEVEL_INFO, msg, True) + full = messages.SELECTION_DELETED + + if full or brief: + self.presentMessage(full, brief) + self.utilities.updateCachedTextSelection(event.source) + return + + string = self.utilities.deletedText(event) + if self.utilities.isDeleteCommandTextDeletionEvent(event): + msg = "DEFAULT: Deletion is believed to be due to Delete command" + debug.printMessage(debug.LEVEL_INFO, msg, True) + string = self.utilities.getCharacterAtOffset(event.source) + elif self.utilities.isBackSpaceCommandTextDeletionEvent(event): + msg = "DEFAULT: Deletion is believed to be due to BackSpace command" + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + msg = "DEFAULT: Event is not being presented due to lack of cause" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if len(string) == 1: + self.speakCharacter(string) + else: + voice = self.speechGenerator.voice(string=string) + string = self.utilities.adjustForRepeats(string) + self.speakMessage(string, voice) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if not self.utilities.isPresentableTextChangedEventForLocusOfFocus(event): + return + + self.utilities.handleUndoTextEvent(event) + + if event.source == cthulhu_state.locusOfFocus and self.utilities.isAutoTextEvent(event): + self._saveFocusedObjectInfo(event.source) + cthulhu.setLocusOfFocus(event, event.source, False) + self.updateBraille(event.source) + + full, brief = "", "" + if self.utilities.isClipboardTextChangedEvent(event): + msg = "DEFAULT: Insertion is believed to be due to clipboard paste" + debug.printMessage(debug.LEVEL_INFO, msg, True) + full, brief = messages.CLIPBOARD_PASTED_FULL, messages.CLIPBOARD_PASTED_BRIEF + elif self.utilities.isSelectedTextRestoredEvent(event): + msg = "DEFAULT: Insertion is believed to be due to restoring selected text" + debug.printMessage(debug.LEVEL_INFO, msg, True) + full = messages.SELECTION_RESTORED + + if full or brief: + self.presentMessage(full, brief) + self.utilities.updateCachedTextSelection(event.source) + return + + speakString = True + + # Because some implementations are broken. + string = self.utilities.insertedText(event) + + if self.utilities.lastInputEventWasPageSwitch(): + msg = "DEFAULT: Insertion is believed to be due to page switch" + debug.printMessage(debug.LEVEL_INFO, msg, True) + speakString = False + elif self.utilities.lastInputEventWasCommand(): + msg = "DEFAULT: Insertion is believed to be due to command" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif self.utilities.isMiddleMouseButtonTextInsertionEvent(event): + msg = "DEFAULT: Insertion is believed to be due to middle mouse button" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif self.utilities.isEchoableTextInsertionEvent(event): + msg = "DEFAULT: Insertion is believed to be echoable" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif self.utilities.isAutoTextEvent(event): + msg = "DEFAULT: Insertion is believed to be auto text event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif self.utilities.isSelectedTextInsertionEvent(event): + msg = "DEFAULT: Insertion is also selected" + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + msg = "DEFAULT: Not speaking inserted string due to lack of cause" + debug.printMessage(debug.LEVEL_INFO, msg, True) + speakString = False + + if speakString: + if len(string) == 1: + self.speakCharacter(string) + else: + voice = self.speechGenerator.voice(obj=event.source, string=string) + string = self.utilities.adjustForRepeats(string) + self.speakMessage(string, voice) + + if len(string) != 1: + return + + if _settingsManager.getSetting('enableEchoBySentence') \ + and self.echoPreviousSentence(event.source): + return + + if _settingsManager.getSetting('enableEchoByWord'): + self.echoPreviousWord(event.source) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + obj = event.source + + # We won't handle undo here as it can lead to double-presentation. + # If there is an application for which text-changed events are + # missing upon undo, handle them in an app or toolkit script. + + self.utilities.handleTextSelectionChange(obj) + self.updateBraille(obj) + + def onColumnReordered(self, event): + """Callback for object:column-reordered accessibility events.""" + + if not self.utilities.lastInputEventWasTableSort(): + return + + if event.source != self.utilities.getTable(cthulhu_state.locusOfFocus): + return + + self.pointOfReference['last-table-sort-time'] = time.time() + self.presentMessage(messages.TABLE_REORDERED_COLUMNS) + + def onRowReordered(self, event): + """Callback for object:row-reordered accessibility events.""" + + if not self.utilities.lastInputEventWasTableSort(): + return + + if event.source != self.utilities.getTable(cthulhu_state.locusOfFocus): + return + + self.pointOfReference['last-table-sort-time'] = time.time() + self.presentMessage(messages.TABLE_REORDERED_ROWS) + + def onValueChanged(self, event): + """Called whenever an object's value changes. Currently, the + value changes for non-focused objects are ignored. + + Arguments: + - event: the Event + """ + + obj = event.source + role = AXObject.get_role(obj) + + try: + value = obj.queryValue() + currentValue = value.currentValue + except NotImplementedError: + tokens = ["DEFAULT:", obj, "doesn't implement AtspiValue"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + except Exception: + tokens = ["DEFAULT: Exception getting current value for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if "oldValue" in self.pointOfReference \ + and (currentValue == self.pointOfReference["oldValue"]): + return + + isProgressBarUpdate, msg = self.utilities.isProgressBarUpdate(obj) + tokens = ["DEFAULT: Is progress bar update:", isProgressBarUpdate, ",", msg] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not isProgressBarUpdate and obj != cthulhu_state.locusOfFocus: + tokens = ["DEFAULT: Source != locusOfFocus (", cthulhu_state.locusOfFocus, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if role == Atspi.Role.SPIN_BUTTON: + self._saveFocusedObjectInfo(event.source) + + self.pointOfReference["oldValue"] = currentValue + self.updateBraille(obj, isProgressBarUpdate=isProgressBarUpdate) + speech.speak(self.speechGenerator.generateSpeech( + obj, alreadyFocused=True, isProgressBarUpdate=isProgressBarUpdate)) + self.__play(self.soundGenerator.generateSound( + obj, alreadyFocused=True, isProgressBarUpdate=isProgressBarUpdate)) + + def onWindowActivated(self, event): + """Called whenever a toplevel window is activated. + + Arguments: + - event: the Event + """ + + window = AXObject.find_real_app_and_window_for(event.source)[1] + if not self.utilities.canBeActiveWindow(window, False): + return + + if self.utilities.isSameObject(window, cthulhu_state.activeWindow): + msg = "DEFAULT: Event is for active window." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + self.pointOfReference = {} + + cthulhu.setActiveWindow(window) + if self.utilities.isKeyGrabEvent(event): + msg = "DEFAULT: Ignoring event. Likely from key grab." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if AXObject.get_child_count(window) == 1: + child = AXObject.get_child(window, 0) + if AXObject.get_role(child) == Atspi.Role.MENU: + cthulhu.setLocusOfFocus(event, child) + return + + cthulhu.setLocusOfFocus(event, cthulhu_state.activeWindow) + + def onWindowCreated(self, event): + """Callback for window:create accessibility events.""" + + pass + + def onWindowDestroyed(self, event): + """Callback for window:destroy accessibility events.""" + + pass + + def onWindowDeactivated(self, event): + """Called whenever a toplevel window is deactivated. + + Arguments: + - event: the Event + """ + + if self.utilities.inMenu(): + msg = "DEFAULT: Ignoring event. In menu." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if event.source != cthulhu_state.activeWindow: + tokens = ["DEFAULT: Ignoring event. Not for active window", + cthulhu_state.activeWindow, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + if self.utilities.isKeyGrabEvent(event): + msg = "DEFAULT: Ignoring event. Likely from key grab." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.quit() + + if self.learnModePresenter.is_active(): + self.learnModePresenter.quit() + + self.pointOfReference = {} + + if not self.utilities.eventIsUserTriggered(event): + msg = "DEFAULT: Not clearing state. Event is not user triggered." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "DEFAULT: Clearing state." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + cthulhu.setLocusOfFocus(event, None) + cthulhu.setActiveWindow(None) + _scriptManager.setActiveScript(None, "Window deactivated") + + def onClipboardContentsChanged(self, *args): + if self.flatReviewPresenter.is_active(): + return + + if not self.utilities.objectContentsAreInClipboard(): + return + + if not self.utilities.topLevelObjectIsActiveAndCurrent(): + return + + if self.utilities.lastInputEventWasCopy(): + self.presentMessage(messages.CLIPBOARD_COPIED_FULL, messages.CLIPBOARD_COPIED_BRIEF) + return + + if not self.utilities.lastInputEventWasCut(): + return + + if AXUtilities.is_editable(cthulhu_state.locusOfFocus): + return + + self.presentMessage(messages.CLIPBOARD_CUT_FULL, messages.CLIPBOARD_CUT_BRIEF) + + ######################################################################## + # # + # Methods for presenting content # + # # + ######################################################################## + + def _presentTextAtNewCaretPosition(self, event, otherObj=None): + obj = otherObj or event.source + self.updateBrailleForNewCaretPosition(obj) + if self._inSayAll: + msg = "DEFAULT: Not presenting text because SayAll is active" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.utilities.lastInputEventWasLineNav(): + msg = "DEFAULT: Presenting result of line nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayLine(obj) + return + + if self.utilities.lastInputEventWasWordNav(): + msg = "DEFAULT: Presenting result of word nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayWord(obj) + return + + if self.utilities.lastInputEventWasCharNav(): + msg = "DEFAULT: Presenting result of char nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayCharacter(obj) + return + + if self.utilities.lastInputEventWasPageNav(): + msg = "DEFAULT: Presenting result of page nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayLine(obj) + return + + if self.utilities.lastInputEventWasLineBoundaryNav(): + msg = "DEFAULT: Presenting result of line boundary nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayCharacter(obj) + return + + if self.utilities.lastInputEventWasFileBoundaryNav(): + msg = "DEFAULT: Presenting result of file boundary nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayLine(obj) + return + + if self.utilities.lastInputEventWasPrimaryMouseClick() \ + or self.utilities.lastInputEventWasPrimaryMouseRelease(): + start, end, string = self.utilities.getCachedTextSelection(event.source) + if not string: + msg = "DEFAULT: Presenting result of primary mouse button event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayLine(obj) + return + + def _rewindSayAll(self, context, minCharCount=10): + if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'): + return False + + index = self._sayAllContexts.index(context) + self._sayAllContexts = self._sayAllContexts[0:index] + while self._sayAllContexts: + context = self._sayAllContexts.pop() + if context.endOffset - context.startOffset > minCharCount: + break + + try: + text = context.obj.queryText() + except Exception: + pass + else: + cthulhu.setLocusOfFocus(None, context.obj, notifyScript=False) + text.setCaretOffset(context.startOffset) + + self.sayAll(None, context.obj, context.startOffset) + return True + + def _fastForwardSayAll(self, context): + if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'): + return False + + try: + text = context.obj.queryText() + except Exception: + pass + else: + cthulhu.setLocusOfFocus(None, context.obj, notifyScript=False) + text.setCaretOffset(context.endOffset) + + self.sayAll(None, context.obj, context.endOffset) + return True + + def __sayAllProgressCallback(self, context, progressType): + # [[[TODO: WDW - this needs work. Need to be able to manage + # the monitoring of progress and couple that with both updating + # the visual progress of what is being spoken as well as + # positioning the cursor when speech has stopped.]]] + # + try: + text = context.obj.queryText() + char = text.getText(context.currentOffset, context.currentOffset+1) + except Exception: + return + + # Setting the caret at the offset of an embedded object results in + # focus changes. + if char == self.EMBEDDED_OBJECT_CHARACTER: + return + + if progressType == speechserver.SayAllContext.PROGRESS: + cthulhu.emitRegionChanged( + context.obj, context.currentOffset, context.currentEndOffset, cthulhu.SAY_ALL) + return + + if progressType == speechserver.SayAllContext.INTERRUPTED: + if isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + self._sayAllIsInterrupted = True + lastKey = cthulhu_state.lastInputEvent.event_string + if lastKey == "Down" and self._fastForwardSayAll(context): + return + elif lastKey == "Up" and self._rewindSayAll(context): + return + + self._inSayAll = False + self._sayAllContexts = [] + cthulhu.emitRegionChanged(context.obj, context.currentOffset) + text.setCaretOffset(context.currentOffset) + elif progressType == speechserver.SayAllContext.COMPLETED: + cthulhu.setLocusOfFocus(None, context.obj, notifyScript=False) + cthulhu.emitRegionChanged(context.obj, context.currentOffset, mode=cthulhu.SAY_ALL) + text.setCaretOffset(context.currentOffset) + + # If there is a selection, clear it. See bug #489504 for more details. + # + if text.getNSelections() > 0: + text.setSelection(0, context.currentOffset, context.currentOffset) + + def inSayAll(self, treatInterruptedAsIn=True): + if self._inSayAll: + msg = "DEFAULT: In SayAll" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._sayAllIsInterrupted: + msg = "DEFAULT: SayAll is interrupted" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return treatInterruptedAsIn + + msg = "DEFAULT: Not in SayAll" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def echoPreviousSentence(self, obj): + """Speaks the sentence prior to the caret, as long as there is + a sentence prior to the caret and there is no intervening sentence + delimiter between the caret and the end of the sentence. + + The entry condition for this method is that the character + prior to the current caret position is a sentence delimiter, + and it's what caused this method to be called in the first + place. + + Arguments: + - obj: an Accessible object that implements the AccessibleText + interface. + """ + + try: + text = obj.queryText() + except NotImplementedError: + return False + + offset = text.caretOffset - 1 + previousOffset = text.caretOffset - 2 + if (offset < 0 or previousOffset < 0): + return False + + [currentChar, startOffset, endOffset] = \ + text.getTextAtOffset(offset, Atspi.TextBoundaryType.CHAR) + [previousChar, startOffset, endOffset] = \ + text.getTextAtOffset(previousOffset, Atspi.TextBoundaryType.CHAR) + if not self.utilities.isSentenceDelimiter(currentChar, previousChar): + return False + + # OK - we seem to be cool so far. So...starting with what + # should be the last character in the sentence (caretOffset - 2), + # work our way to the beginning of the sentence, stopping when + # we hit another sentence delimiter. + # + sentenceEndOffset = text.caretOffset - 2 + sentenceStartOffset = sentenceEndOffset + + while sentenceStartOffset >= 0: + [currentChar, startOffset, endOffset] = \ + text.getTextAtOffset(sentenceStartOffset, + Atspi.TextBoundaryType.CHAR) + [previousChar, startOffset, endOffset] = \ + text.getTextAtOffset(sentenceStartOffset-1, + Atspi.TextBoundaryType.CHAR) + if self.utilities.isSentenceDelimiter(currentChar, previousChar): + break + else: + sentenceStartOffset -= 1 + + # If we came across a sentence delimiter before hitting any + # text, we really don't have a previous sentence. + # + # Otherwise, get the sentence. Remember we stopped when we + # hit a sentence delimiter, so the sentence really starts at + # sentenceStartOffset + 1. getText also does not include + # the character at sentenceEndOffset, so we need to adjust + # for that, too. + # + if sentenceStartOffset == sentenceEndOffset: + return False + else: + sentence = self.utilities.substring(obj, sentenceStartOffset + 1, + sentenceEndOffset + 1) + + voice = self.speechGenerator.voice(obj=obj, string=sentence) + sentence = self.utilities.adjustForRepeats(sentence) + self.speakMessage(sentence, voice) + return True + + def echoPreviousWord(self, obj, offset=None): + """Speaks the word prior to the caret, as long as there is + a word prior to the caret and there is no intervening word + delimiter between the caret and the end of the word. + + The entry condition for this method is that the character + prior to the current caret position is a word delimiter, + and it's what caused this method to be called in the first + place. + + Arguments: + - obj: an Accessible object that implements the AccessibleText + interface. + - offset: if not None, the offset within the text to use as the + end of the word. + """ + + try: + text = obj.queryText() + except NotImplementedError: + return False + + if not offset: + if text.caretOffset == -1: + offset = text.characterCount + else: + offset = text.caretOffset - 1 + + if (offset < 0): + return False + + [char, startOffset, endOffset] = \ + text.getTextAtOffset( \ + offset, + Atspi.TextBoundaryType.CHAR) + if not self.utilities.isWordDelimiter(char): + return False + + # OK - we seem to be cool so far. So...starting with what + # should be the last character in the word (caretOffset - 2), + # work our way to the beginning of the word, stopping when + # we hit another word delimiter. + # + wordEndOffset = offset - 1 + wordStartOffset = wordEndOffset + + while wordStartOffset >= 0: + [char, startOffset, endOffset] = \ + text.getTextAtOffset( \ + wordStartOffset, + Atspi.TextBoundaryType.CHAR) + if self.utilities.isWordDelimiter(char): + break + else: + wordStartOffset -= 1 + + # If we came across a word delimiter before hitting any + # text, we really don't have a previous word. + # + # Otherwise, get the word. Remember we stopped when we + # hit a word delimiter, so the word really starts at + # wordStartOffset + 1. getText also does not include + # the character at wordEndOffset, so we need to adjust + # for that, too. + # + if wordStartOffset == wordEndOffset: + return False + else: + word = self.utilities.\ + substring(obj, wordStartOffset + 1, wordEndOffset + 1) + + voice = self.speechGenerator.voice(obj=obj, string=word) + word = self.utilities.adjustForRepeats(word) + self.speakMessage(word, voice) + return True + + def sayCharacter(self, obj): + """Speak the character at the caret. + + Arguments: + - obj: an Accessible object that implements the AccessibleText + interface + """ + + text = obj.queryText() + offset = text.caretOffset + + # If we have selected text and the last event was a move to the + # right, then speak the character to the left of where the text + # caret is (i.e. the selected character). + # + eventString, mods = self.utilities.lastKeyAndModifiers() + if (mods & keybindings.SHIFT_MODIFIER_MASK) \ + and eventString in ["Right", "Down"]: + offset -= 1 + + character, startOffset, endOffset = text.getTextAtOffset( + offset, Atspi.TextBoundaryType.CHAR) + cthulhu.emitRegionChanged(obj, startOffset, endOffset, cthulhu.CARET_TRACKING) + + if not character or character == '\r': + character = "\n" + + speakBlankLines = _settingsManager.getSetting('speakBlankLines') + if character == "\n": + line = text.getTextAtOffset(max(0, offset), + Atspi.TextBoundaryType.LINE_START) + if not line[0] or line[0] == "\n": + # This is a blank line. Announce it if the user requested + # that blank lines be spoken. + if speakBlankLines: + self.speakMessage(messages.BLANK, interrupt=False) + return + + if character in ["\n", "\r\n"]: + # This is a blank line. Announce it if the user requested + # that blank lines be spoken. + if speakBlankLines: + self.speakMessage(messages.BLANK, interrupt=False) + return + else: + self.speakMisspelledIndicator(obj, offset) + self.speakCharacter(character) + + self.pointOfReference["lastTextUnitSpoken"] = "char" + + def sayLine(self, obj): + """Speaks the line of an AccessibleText object that contains the + caret, unless the line is empty in which case it's ignored. + + Arguments: + - obj: an Accessible object that implements the AccessibleText + interface + """ + + [line, caretOffset, startOffset] = self.getTextLineAtCaret(obj) + if len(line) and line != "\n": + indentationDescription = self.utilities.indentationDescription(line) + if indentationDescription: + self.speakMessage(indentationDescription) + + endOffset = startOffset + len(line) + cthulhu.emitRegionChanged(obj, startOffset, endOffset, cthulhu.CARET_TRACKING) + + utterance = [] + split = self.utilities.splitSubstringByLanguage(obj, startOffset, endOffset) + for start, end, string, language, dialect in split: + if not string: + continue + + voice = self.speechGenerator.voice( + obj=obj, string=string, language=language, dialect=dialect) + string = self.utilities.adjustForLinks(obj, string, start) + string = self.utilities.adjustForRepeats(string) + if self.utilities.shouldVerbalizeAllPunctuation(obj): + string = self.utilities.verbalizeAllPunctuation(string) + + # Some synthesizers will verbalize the whitespace, so if we've already + # described it, prevent double-presentation by stripping it off. + if not utterance and indentationDescription: + string = string.lstrip() + + result = [string] + result.extend(voice) + utterance.append(result) + speech.speak(utterance) + else: + # Speak blank line if appropriate. + # + self.sayCharacter(obj) + + self.pointOfReference["lastTextUnitSpoken"] = "line" + + def sayPhrase(self, obj, startOffset, endOffset): + """Speaks the text of an Accessible object between the start and + end offsets, unless the phrase is empty in which case it's ignored. + + Arguments: + - obj: an Accessible object that implements the AccessibleText + interface + - startOffset: the start text offset. + - endOffset: the end text offset. + """ + + phrase = self.utilities.expandEOCs(obj, startOffset, endOffset) + if not phrase: + return + + if len(phrase) > 1 or phrase.isalnum(): + result = self.utilities.indentationDescription(phrase) + if result: + self.speakMessage(result) + + cthulhu.emitRegionChanged(obj, startOffset, endOffset, cthulhu.CARET_TRACKING) + + voice = self.speechGenerator.voice(obj=obj, string=phrase) + phrase = self.utilities.adjustForRepeats(phrase) + if self.utilities.shouldVerbalizeAllPunctuation(obj): + phrase = self.utilities.verbalizeAllPunctuation(phrase) + + utterance = [phrase] + utterance.extend(voice) + speech.speak(utterance) + else: + self.speakCharacter(phrase) + + self.pointOfReference["lastTextUnitSpoken"] = "phrase" + + def sayWord(self, obj): + """Speaks the word at the caret, taking into account the previous caret position.""" + + try: + text = obj.queryText() + offset = text.caretOffset + except Exception: + self.sayCharacter(obj) + return + + word, startOffset, endOffset = \ + self.utilities.getWordAtOffsetAdjustedForNavigation(obj, offset) + + # Announce when we cross a hard line boundary. + if "\n" in word: + if _settingsManager.getSetting('enableSpeechIndentation'): + self.speakCharacter("\n") + if word.startswith("\n"): + startOffset += 1 + elif word.endswith("\n"): + endOffset -= 1 + word = text.getText(startOffset, endOffset) + + # sayPhrase is useful because it handles punctuation verbalization, but we don't want + # to trigger its whitespace presentation. + matches = list(re.finditer(r"\S+", word)) + if matches: + startOffset += matches[0].start() + endOffset -= len(word) - matches[-1].end() + word = text.getText(startOffset, endOffset) + + string = word.replace("\n", "\\n") + msg = ( + f"DEFAULT: Final word at offset {offset} is '{string}' " + f"({startOffset}-{endOffset})" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.speakMisspelledIndicator(obj, startOffset) + self.sayPhrase(obj, startOffset, endOffset) + self.pointOfReference["lastTextUnitSpoken"] = "word" + + def presentObject(self, obj, **args): + interrupt = args.get("interrupt", False) + tokens = ["DEFAULT: Presenting object", obj, ". Interrupt:", interrupt] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not args.get("speechonly", False): + self.updateBraille(obj, **args) + utterances = self.speechGenerator.generateSpeech(obj, **args) + speech.speak(utterances, interrupt=interrupt) + + def stopSpeechOnActiveDescendantChanged(self, event): + """Whether or not speech should be stopped prior to setting the + locusOfFocus in onActiveDescendantChanged. + + Arguments: + - event: the Event + + Returns True if speech should be stopped; False otherwise. + """ + + if not event.any_data: + return True + + # In an object which manages its descendants, the + # 'descendants' may really be a single object which changes + # its name. If the name-change occurs followed by the active + # descendant changing (to the same object) we won't present + # the locusOfFocus because it hasn't changed. Thus we need to + # be sure not to cut of the presentation of the name-change + # event. + + if cthulhu_state.locusOfFocus == event.any_data: + names = self.pointOfReference.get('names', {}) + oldName = names.get(hash(cthulhu_state.locusOfFocus), '') + if not oldName or AXObject.get_name(event.any_data) == oldName: + return False + + if event.source == cthulhu_state.locusOfFocus == AXObject.get_parent(event.any_data): + return False + + return True + + def getFlatReviewContext(self): + """Returns the flat review context, creating one if necessary.""" + + return self.flatReviewPresenter.get_or_create_context(self) + + def updateBrailleReview(self, targetCursorCell=0): + """Obtains the braille regions for the current flat review line + and displays them on the braille display. If the targetCursorCell + is non-0, then an attempt will be made to position the review cursor + at that cell. Otherwise, we will pan in display-sized increments + to show the review cursor.""" + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: update review disabled", True) + return + + [regions, regionWithFocus] = self.flatReviewPresenter.get_braille_regions(self) + if not regions: + regions = [] + regionWithFocus = None + + line = self.getNewBrailleLine() + self.addBrailleRegionsToLine(regions, line) + braille.setLines([line]) + self.setBrailleFocus(regionWithFocus, False) + if regionWithFocus and not targetCursorCell: + offset = regionWithFocus.brailleOffset + regionWithFocus.cursorOffset + tokens = ["DEFAULT: Update to", offset, "in", regionWithFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.panBrailleToOffset(offset) + + if self.justEnteredFlatReviewMode: + self.refreshBraille(True, self.targetCursorCell) + self.justEnteredFlatReviewMode = False + else: + self.refreshBraille(True, targetCursorCell) + + def _setFlatReviewContextToBeginningOfBrailleDisplay(self): + """Sets the character of interest to be the first character showing + at the beginning of the braille display.""" + + # The first character on the flat review line has to be in object with text. + def isTextOrComponent(x): + return isinstance(x, (braille.ReviewText, braille.ReviewComponent)) + + regions = self.flatReviewPresenter.get_braille_regions(self)[0] + regions = list(filter(isTextOrComponent, regions)) + tokens = ["DEFAULT: Text/Component regions on line:"] + for region in regions: + tokens.extend(["\n", region]) + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # TODO - JD: The current code was stopping on the first region which met the + # following condition. Is that definitely the right thing to do? Assume so for now. + # Also: Should the default script be accessing things like the viewport directly?? + def isMatch(x): + return x is not None and x.brailleOffset + len(x.string) > braille.viewport[0] + + regions = list(filter(isMatch, regions)) + if not regions: + msg = "DEFAULT: Could not find review region to move to start of display" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + tokens = ["DEFAULT: Candidates for start of display:"] + for region in regions: + tokens.extend(["\n", region]) + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + + # TODO - JD: Again, for now we're preserving the original behavior of choosing the first. + region = regions[0] + position = max(region.brailleOffset, braille.viewport[0]) + if region.contracted: + offset = region.inPos[position - region.brailleOffset] + else: + offset = position - region.brailleOffset + if isinstance(region.zone, flat_review.TextZone): + offset += region.zone.startOffset + msg = f"DEFAULT: Offset for region: {offset}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + [word, charOffset] = region.zone.getWordAtOffset(offset) + if word: + tokens = ["DEFAULT: Setting start of display to", word, ", ", charOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + context = self.getFlatReviewContext() + context.setCurrent( + word.zone.line.index, + word.zone.index, + word.index, + charOffset) + else: + tokens = ["DEFAULT: Setting start of display to", region.zone] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + context = self.getFlatReviewContext() + context.setCurrent( + region.zone.line.index, + region.zone.index, + 0, # word index + 0) # character index + + def find(self, query=None): + """Searches for the specified query. If no query is specified, + it searches for the query specified in the Cthulhu Find dialog. + + Arguments: + - query: The search query to find. + """ + + if not query: + query = find.getLastQuery() + if query: + context = self.getFlatReviewContext() + location = query.findQuery(context) + if not location: + self.presentMessage(messages.STRING_NOT_FOUND) + else: + context.setCurrent(location.lineIndex, location.zoneIndex, \ + location.wordIndex, location.charIndex) + self.flatReviewPresenter.present_item(self) + self.targetCursorCell = self.getBrailleCursorCell() + + def textLines(self, obj, offset=None): + """Creates a generator that can be used to iterate over each line + of a text object, starting at the caret offset. + + Arguments: + - obj: an Accessible that has a text specialization + + Returns an iterator that produces elements of the form: + [SayAllContext, acss], where SayAllContext has the text to be + spoken and acss is an ACSS instance for speaking the text. + """ + + self._sayAllIsInterrupted = False + try: + text = obj.queryText() + except Exception: + self._inSayAll = False + self._sayAllContexts = [] + return + + self._inSayAll = True + length = text.characterCount + if offset is None: + offset = text.caretOffset + + # Determine the correct "say all by" mode to use. + # + sayAllStyle = _settingsManager.getSetting('sayAllStyle') + if sayAllStyle == settings.SAYALL_STYLE_SENTENCE: + mode = Atspi.TextBoundaryType.SENTENCE_START + elif sayAllStyle == settings.SAYALL_STYLE_LINE: + mode = Atspi.TextBoundaryType.LINE_START + else: + mode = Atspi.TextBoundaryType.LINE_START + + priorObj = obj + + # Get the next line of text to read + # + done = False + while not done: + speech.speak(self.speechGenerator.generateContext(obj, priorObj=priorObj)) + + lastEndOffset = -1 + while offset < length: + [lineString, startOffset, endOffset] = text.getTextAtOffset( + offset, mode) + + # Some applications that don't support sentence boundaries + # will provide the line boundary results instead; others + # will return nothing. + # + if not lineString: + mode = Atspi.TextBoundaryType.LINE_START + [lineString, startOffset, endOffset] = \ + text.getTextAtOffset(offset, mode) + + if endOffset > text.characterCount: + tokens = ["DEFAULT: end offset", endOffset, " > character count", + text.characterCount, + "resulting from text.getTextAtOffset(", offset, mode, ") for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + endOffset = text.characterCount + + # [[[WDW - HACK: this is here because getTextAtOffset + # tends not to be implemented consistently across toolkits. + # Sometimes it behaves properly (i.e., giving us an endOffset + # that is the beginning of the next line), sometimes it + # doesn't (e.g., giving us an endOffset that is the end of + # the current line). So...we hack. The whole 'max' deal + # is to account for lines that might be a brazillion lines + # long.]]] + # + if endOffset == lastEndOffset: + offset = max(offset + 1, lastEndOffset + 1) + lastEndOffset = endOffset + continue + + lastEndOffset = endOffset + offset = endOffset + + voice = self.speechGenerator.voice(obj=obj, string=lineString) + if voice and isinstance(voice, list): + voice = voice[0] + + lineString = \ + self.utilities.adjustForLinks(obj, lineString, startOffset) + lineString = self.utilities.adjustForRepeats(lineString) + + context = speechserver.SayAllContext( + obj, lineString, startOffset, endOffset) + tokens = ["DEFAULT:", context] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._sayAllContexts.append(context) + self.eventSynthesizer.scroll_into_view(obj, startOffset, endOffset) + yield [context, voice] + + moreLines = False + relation = AXObject.get_relation(obj, Atspi.RelationType.FLOWS_TO) + if relation: + priorObj = obj + obj = relation.getTarget(0) + + try: + text = obj.queryText() + except NotImplementedError: + return + + length = text.characterCount + offset = 0 + moreLines = True + break + if not moreLines: + done = True + + self._inSayAll = False + self._sayAllContexts = [] + + msg = "DEFAULT: textLines complete. Verifying SayAll status" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.inSayAll() + + def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None): + """To-be-removed. Returns the string, caretOffset, startOffset.""" + + try: + text = obj.queryText() + offset = text.caretOffset + characterCount = text.characterCount + except NotImplementedError: + return ["", 0, 0] + except Exception: + tokens = ["DEFAULT: Exception getting offset and length for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return ["", 0, 0] + + if characterCount == 0: + return ["", 0, 0] + + targetOffset = startOffset + if targetOffset is None: + targetOffset = max(0, offset) + + # The offset might be positioned at the very end of the text area. + # In these cases, calling text.getTextAtOffset on an offset that's + # not positioned to a character can yield unexpected results. In + # particular, we'll see the Gecko toolkit return a start and end + # offset of (0, 0), and we'll see other implementations, such as + # gedit, return reasonable results (i.e., gedit will give us the + # last line). + # + # In order to accommodate the differing behavior of different + # AT-SPI implementations, we'll make sure we give getTextAtOffset + # the offset of an actual character. Then, we'll do a little check + # to see if that character is a newline - if it is, we'll treat it + # as the line. + # + if targetOffset == characterCount: + fixedTargetOffset = max(0, targetOffset - 1) + character = text.getText(fixedTargetOffset, fixedTargetOffset + 1) + else: + fixedTargetOffset = targetOffset + character = None + + if (targetOffset == characterCount) \ + and (character == "\n"): + lineString = "" + startOffset = fixedTargetOffset + else: + # Get the line containing the caret. [[[TODO: HACK WDW - If + # there's only 1 character in the string, well, we get it. We + # do this because Gecko's implementation of getTextAtOffset + # is broken if there is just one character in the string.]]] + # + if (characterCount == 1): + lineString = text.getText(fixedTargetOffset, fixedTargetOffset + 1) + startOffset = fixedTargetOffset + else: + if fixedTargetOffset == -1: + fixedTargetOffset = characterCount + try: + [lineString, startOffset, endOffset] = text.getTextAtOffset( + fixedTargetOffset, Atspi.TextBoundaryType.LINE_START) + + # Chrome fix: Handle case where get_line_at_offset returns the line + # after the offset, which seems to happen when the character at offset + # is an embedded object at a line boundary. + if 0 <= fixedTargetOffset < startOffset: + backup_offset = fixedTargetOffset - 1 + tokens = [f"DEFAULT: Start offset {startOffset} is greater than target offset {fixedTargetOffset}. Trying with offset {backup_offset}"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + [lineString, startOffset, endOffset] = text.getTextAtOffset( + backup_offset, Atspi.TextBoundaryType.LINE_START) + + except Exception: + return ["", 0, 0] + + # Sometimes we get the trailing line-feed-- remove it + # It is important that these are in order. + # In some circumstances we might get: + # word word\r\n + # so remove \n, and then remove \r. + # See bgo#619332. + # + lineString = lineString.rstrip('\n') + lineString = lineString.rstrip('\r') + + return [lineString, text.caretOffset, startOffset] + + def phoneticSpellCurrentItem(self, itemString): + """Phonetically spell the current flat review word or line. + + Arguments: + - itemString: the string to phonetically spell. + """ + + for (charIndex, character) in enumerate(itemString): + voice = self.speechGenerator.voice(string=character) + phoneticString = phonnames.getPhoneticName(character.lower()) + self.speakMessage(phoneticString, voice) + + def _saveLastCursorPosition(self, obj, caretOffset): + """Save away the current text cursor position for next time. + + Arguments: + - obj: the current accessible + - caretOffset: the cursor position within this object + """ + + prevObj, prevOffset = self.pointOfReference.get("lastCursorPosition", (None, -1)) + self.pointOfReference["penultimateCursorPosition"] = prevObj, prevOffset + self.pointOfReference["lastCursorPosition"] = obj, caretOffset + + def systemBeep(self): + """Rings the system bell. This is really a hack. Ideally, we want + a method that will present an earcon (any sound designated for the + purpose of representing an error, event etc) + """ + + print("\a") + + def speakMisspelledIndicator(self, obj, offset): + """Speaks an announcement indicating that a given word is misspelled. + + Arguments: + - obj: An accessible which implements the accessible text interface. + - offset: Offset in the accessible's text for which to retrieve the + attributes. + """ + + if _settingsManager.getSetting('speakMisspelledIndicator'): + try: + text = obj.queryText() + except Exception: + return + # If we're on whitespace, we cannot be on a misspelled word. + # + charAndOffsets = \ + text.getTextAtOffset(offset, Atspi.TextBoundaryType.CHAR) + if not charAndOffsets[0].strip() \ + or self.utilities.isWordDelimiter(charAndOffsets[0]): + self._lastWordCheckedForSpelling = charAndOffsets[0] + return + + wordAndOffsets = \ + text.getTextAtOffset(offset, Atspi.TextBoundaryType.WORD_START) + if self.utilities.isWordMisspelled(obj, offset) \ + and wordAndOffsets[0] != self._lastWordCheckedForSpelling: + self.speakMessage(messages.MISSPELLED) + # Store this word so that we do not continue to present the + # presence of the red squiggly as the user arrows amongst + # the characters. + # + self._lastWordCheckedForSpelling = wordAndOffsets[0] + + ############################################################################ + # # + # Presentation methods # + # (scripts should not call methods in braille.py or speech.py directly) # + # # + ############################################################################ + + def presentationInterrupt(self): + """Convenience method to interrupt presentation of whatever is being + presented at the moment.""" + + msg = "DEFAULT: Interrupting presentation" + debug.printMessage(debug.LEVEL_INFO, msg, True) + speech.stop() + braille.killFlash() + + def presentKeyboardEvent(self, event): + """Convenience method to present the KeyboardEvent event. Returns True + if we fully present the event; False otherwise.""" + + if not event.isPressedKey(): + self._sayAllIsInterrupted = False + self.utilities.clearCachedCommandState() + + if not event.shouldEcho or event.isCthulhuModified(): + return False + + role = AXObject.get_role(cthulhu_state.locusOfFocus) + if role in [Atspi.Role.DIALOG, Atspi.Role.FRAME, Atspi.Role.WINDOW]: + focusedObject = AXUtilities.get_focused_object(cthulhu_state.activeWindow) + if focusedObject: + cthulhu.setLocusOfFocus(None, focusedObject, False) + role = AXObject.get_role(focusedObject) + + if role == Atspi.Role.PASSWORD_TEXT and not event.isLockingKey(): + return False + + if not event.isPressedKey(): + return False + + braille.displayKeyEvent(event) + cthulhuModifierPressed = event.isCthulhuModifier() and event.isPressedKey() + if event.isCharacterEchoable() and not cthulhuModifierPressed: + return False + + msg = "DEFAULT: Presenting keyboard event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.speakKeyEvent(event) + return True + + def presentMessage(self, fullMessage, briefMessage=None, voice=None, resetStyles=True, + force=False): + """Convenience method to speak a message and 'flash' it in braille. + + Arguments: + - fullMessage: This can be a string or a list. This will be presented + as the message for users whose flash or message verbosity level is + verbose. + - briefMessage: This can be a string or a list. This will be presented + as the message for users whose flash or message verbosity level is + brief. Note that providing no briefMessage will result in the full + message being used for either. Callers wishing to present nothing as + the briefMessage should set briefMessage to an empty string. + - voice: The voice to use when speaking this message. By default, the + "system" voice will be used. + """ + + if not fullMessage: + return + + if briefMessage is None: + briefMessage = fullMessage + + if _settingsManager.getSetting('enableSpeech'): + if not _settingsManager.getSetting('messagesAreDetailed'): + message = briefMessage + else: + message = fullMessage + if message: + self.speakMessage(message, voice=voice, resetStyles=resetStyles, force=force) + + if (_settingsManager.getSetting('enableBraille') \ + or _settingsManager.getSetting('enableBrailleMonitor')) \ + and _settingsManager.getSetting('enableFlashMessages'): + if not _settingsManager.getSetting('flashIsDetailed'): + message = briefMessage + else: + message = fullMessage + if not message: + return + + if isinstance(message[0], list): + message = message[0] + if isinstance(message, list): + message = [i for i in message if isinstance(i, str)] + message = " ".join(message) + + if _settingsManager.getSetting('flashIsPersistent'): + duration = -1 + else: + duration = _settingsManager.getSetting('brailleFlashTime') + + braille.displayMessage(message, flashTime=duration) + + def idleMessage(self): + """Convenience method to tell speech and braille engines to hand off + control to other screen readers.""" + + braille.disableBraille() + + @staticmethod + def __play(sounds, interrupt=True): + if not sounds: + return + + if not isinstance(sounds, list): + sounds = [sounds] + + _player = sound.getPlayer() + _player.play(sounds[0], interrupt) + for i in range(1, len(sounds)): + sound.play(sounds[i], interrupt=False) + + @staticmethod + def addBrailleRegionToLine(region, line): + """Adds the braille region to the line. + + Arguments: + - region: a braille.Region (e.g. what is returned by the braille + generator's generateBraille() method. + - line: a braille.Line + """ + + line.addRegion(region) + + @staticmethod + def addBrailleRegionsToLine(regions, line): + """Adds the braille region to the line. + + Arguments: + - regions: a series of braille.Region instances (a single instance + being what is returned by the braille generator's generateBraille() + method. + - line: a braille.Line + """ + + line.addRegions(regions) + + @staticmethod + def addToLineAsBrailleRegion(string, line): + """Creates a Braille Region out of string and adds it to the line. + + Arguments: + - string: the string to be displayed + - line: a braille.Line + """ + + line.addRegion(braille.Region(string)) + + @staticmethod + def brailleRegionsFromStrings(strings): + """Creates a list of braille regions from the list of strings. + + Arguments: + - strings: a list of strings from which to create the list of + braille Region instances + + Returns the list of braille Region instances + """ + + brailleRegions = [] + for string in strings: + brailleRegions.append(braille.Region(string)) + + return brailleRegions + + @staticmethod + def clearBraille(): + """Clears the logical structure, but keeps the Braille display as is + (until a refresh operation).""" + + braille.clear() + + @staticmethod + def displayBrailleMessage(message, cursor=-1, flashTime=0): + """Displays a single line, setting the cursor to the given position, + ensuring that the cursor is in view. + + Arguments: + - message: the string to display + - cursor: the 0-based cursor position, where -1 (default) means no + cursor + - flashTime: if non-0, the number of milliseconds to display the + regions before reverting back to what was there before. A 0 means + to not do any flashing. A negative number means to display the + message until some other message comes along or the user presses + a cursor routing key. + """ + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: display message disabled", True) + return + + braille.displayMessage(message, cursor, flashTime) + + @staticmethod + def displayBrailleRegions(regionInfo, flashTime=0): + """Displays a list of regions on a single line, setting focus to the + specified region. The regionInfo parameter is something that is + typically returned by a call to braille_generator.generateBraille. + + Arguments: + - regionInfo: a list where the first element is a list of regions + to display and the second element is the region with focus (must + be in the list from element 0) + - flashTime: if non-0, the number of milliseconds to display the + regions before reverting back to what was there before. A 0 means + to not do any flashing. A negative number means to display the + message until some other message comes along or the user presses + a cursor routing key. + """ + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: display regions disabled", True) + return + + braille.displayRegions(regionInfo, flashTime) + + def displayBrailleForObject(self, obj): + """Convenience method for scripts combining the call to the braille + generator for the script with the call to displayBrailleRegions. + + Arguments: + - obj: the accessible object to display in braille + """ + + regions = self.brailleGenerator.generateBraille(obj) + self.displayBrailleRegions(regions) + + @staticmethod + def getBrailleCaretContext(event): + """Gets the accesible and caret offset associated with the given + event. The event should have a BrlAPI event that contains an + argument value that corresponds to a cell on the display. + + Arguments: + - event: an instance of input_event.BrailleEvent. event.event is + the dictionary form of the expanded BrlAPI event. + """ + + return braille.getCaretContext(event) + + @staticmethod + def getBrailleCursorCell(): + """Returns the value of position of the braille cell which has the + cursor. A value of 0 means no cell has the cursor.""" + + return braille.cursorCell + + @staticmethod + def getNewBrailleLine(clearBraille=False, addLine=False): + """Creates a new braille Line. + + Arguments: + - clearBraille: Whether the display should be cleared. + - addLine: Whether the line should be added to the logical display + for painting. + + Returns the new Line. + """ + + if clearBraille: + braille.clear() + line = braille.Line() + if addLine: + braille.addLine(line) + + return line + + @staticmethod + def getNewBrailleComponent(accessible, string, cursorOffset=0, + indicator='', expandOnCursor=False): + """Creates a new braille Component. + + Arguments: + - accessible: the accessible associated with this region + - string: the string to be displayed + - cursorOffset: a 0-based index saying where to draw the cursor + for this Region if it gets focus + + Returns the new Component. + """ + + return braille.Component(accessible, string, cursorOffset, + indicator, expandOnCursor) + + @staticmethod + def getNewBrailleRegion(string, cursorOffset=0, expandOnCursor=False): + """Creates a new braille Region. + + Arguments: + - string: the string to be displayed + - cursorOffset: a 0-based index saying where to draw the cursor + for this Region if it gets focus + + Returns the new Region. + """ + + return braille.Region(string, cursorOffset, expandOnCursor) + + @staticmethod + def getNewBrailleText(accessible, label="", eol="", startOffset=None, + endOffset=None): + + """Creates a new braille Text region. + + Arguments: + - accessible: the accessible associated with this region and which + implements AtkText + - label: an optional label to display + - eol: the endOfLine indicator + + Returns the new Text region. + """ + + return braille.Text(accessible, label, eol, startOffset, endOffset) + + @staticmethod + def isBrailleBeginningShowing(): + """If True, the beginning of the line is showing on the braille + display.""" + + return braille.beginningIsShowing + + @staticmethod + def isBrailleEndShowing(): + """If True, the end of the line is showing on the braille display.""" + + return braille.endIsShowing + + @staticmethod + def panBrailleInDirection(panAmount=0, panToLeft=True): + """Pans the display to the left, limiting the pan to the beginning + of the line being displayed. + + Arguments: + - panAmount: the amount to pan. A value of 0 means the entire + width of the physical display. + - panToLeft: if True, pan to the left; otherwise to the right + + Returns True if a pan actually happened. + """ + + if panToLeft: + return braille.panLeft(panAmount) + else: + return braille.panRight(panAmount) + + @staticmethod + def panBrailleToOffset(offset): + """Automatically pan left or right to make sure the current offset + is showing.""" + + braille.panToOffset(offset) + + @staticmethod + def presentItemsInBraille(items): + """Method to braille a list of items. Scripts should call this + method rather than handling the creation and displaying of a + braille line directly. + + Arguments: + - items: a list of strings to be presented + """ + + line = braille.getShowingLine() + for item in items: + line.addRegion(braille.Region(" " + item)) + + braille.refresh() + + def updateBrailleForNewCaretPosition(self, obj): + """Try to reposition the cursor without having to do a full update.""" + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: update caret disabled", True) + return + + brailleNeedsRepainting = True + line = braille.getShowingLine() + for region in line.regions: + if isinstance(region, braille.Text) and region.accessible == obj: + if region.repositionCursor(): + self.refreshBraille(True) + brailleNeedsRepainting = False + break + + if brailleNeedsRepainting: + self.updateBraille(obj) + + @staticmethod + def refreshBraille(panToCursor=True, targetCursorCell=0, getLinkMask=True, + stopFlash=True): + """This is the method scripts should use to refresh braille rather + than calling self.refreshBraille() directly. The intent is to centralize + such calls into as few places as possible so that we can easily and + safely not perform braille-related functions for users who do not + have braille and/or the braille monitor enabled. + + Arguments: + + - panToCursor: if True, will adjust the viewport so the cursor is + showing. + - targetCursorCell: Only effective if panToCursor is True. + 0 means automatically place the cursor somewhere on the display so + as to minimize movement but show as much of the line as possible. + A positive value is a 1-based target cell from the left side of + the display and a negative value is a 1-based target cell from the + right side of the display. + - getLinkMask: Whether or not we should take the time to get the + attributeMask for links. Reasons we might not want to include + knowing that we will fail and/or it taking an unreasonable + amount of time (AKA Gecko). + - stopFlash: if True, kill any flashed message that may be showing. + """ + + braille.refresh(panToCursor, targetCursorCell, getLinkMask, stopFlash) + + @staticmethod + def setBrailleFocus(region, panToFocus=True, getLinkMask=True): + """Specififes the region with focus. This region will be positioned + at the home position if panToFocus is True. + + Arguments: + - region: the given region, which much be in a line that has been + added to the logical display + - panToFocus: whether or not to position the region at the home + position + - getLinkMask: Whether or not we should take the time to get the + attributeMask for links. Reasons we might not want to include + knowing that we will fail and/or it taking an unreasonable + amount of time (AKA Gecko). + """ + + braille.setFocus(region, panToFocus, getLinkMask) + + @staticmethod + def _setContractedBraille(event): + """Turns contracted braille on or off based upon the event. + + Arguments: + - event: an instance of input_event.BrailleEvent. event.event is + the dictionary form of the expanded BrlAPI event. + """ + + braille.setContractedBraille(event) + + ######################################################################## + # # + # Speech methods # + # (scripts should not call methods in speech.py directly) # + # # + ######################################################################## + + def speakKeyEvent(self, event): + """Method to speak a keyboard event. Scripts should use this method + rather than calling speech.speakKeyEvent directly.""" + + string = None + if event.isPrintableKey(): + string = event.event_string + + voice = self.speechGenerator.voice(string=string) + speech.speakKeyEvent(event, voice) + + def speakCharacter(self, character): + """Method to speak a single character. Scripts should use this + method rather than calling speech.speakCharacter directly.""" + + voice = self.speechGenerator.voice(string=character) + speech.speakCharacter(character, voice) + + def speakMessage(self, string, voice=None, interrupt=True, resetStyles=True, force=False): + """Method to speak a single string. Scripts should use this + method rather than calling speech.speak directly. + + - string: The string to be spoken. + - voice: The voice to use. By default, the "system" voice will + be used. + - interrupt: If True, any current speech should be interrupted + prior to speaking the new text. + """ + + if not _settingsManager.getSetting('enableSpeech') \ + or (_settingsManager.getSetting('onlySpeakDisplayedText') and not force): + return + + voices = _settingsManager.getSetting('voices') + systemVoice = voices.get(settings.SYSTEM_VOICE) + + voice = voice or systemVoice + if voice == systemVoice and resetStyles: + capStyle = _settingsManager.getSetting('capitalizationStyle') + _settingsManager.setSetting('capitalizationStyle', settings.CAPITALIZATION_STYLE_NONE) + self.speechAndVerbosityManager.update_capitalization_style() + + punctStyle = _settingsManager.getSetting('verbalizePunctuationStyle') + _settingsManager.setSetting('verbalizePunctuationStyle', + settings.PUNCTUATION_STYLE_NONE) + self.speechAndVerbosityManager.update_punctuation_level() + + speech.speak(string, voice, interrupt) + + if voice == systemVoice and resetStyles: + _settingsManager.setSetting('capitalizationStyle', capStyle) + self.speechAndVerbosityManager.update_capitalization_style() + + _settingsManager.setSetting('verbalizePunctuationStyle', punctStyle) + self.speechAndVerbosityManager.update_punctuation_level() + + @staticmethod + def presentItemsInSpeech(items): + """Method to speak a list of items. Scripts should call this + method rather than handling the creation and speaking of + utterances directly. + + Arguments: + - items: a list of strings to be presented + """ + + utterances = [] + for item in items: + utterances.append(item) + + speech.speak(utterances) + + def speakUnicodeCharacter(self, character): + """ Speaks some information about an unicode character. + At the moment it just announces the character unicode number but + this information may be changed in the future + + Arguments: + - character: the character to speak information of + """ + speech.speak(messages.UNICODE % \ + self.utilities.unicodeValueString(character)) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/self_voicing.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/self_voicing.py new file mode 100644 index 0000000..e49ec2e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/self_voicing.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""A script to do nothing. This is for self-voicing apps.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import cthulhu.scripts.default as default + +class Script(default.Script): + """A script to do nothing. This is for self-voicing apps.""" + + def __init__(self, app): + """Creates a script for the given application, if necessary. + This method should not be called by anyone except the + script manager. + + Arguments: + - app: the Python Accessible application to create a script for + """ + + default.Script.__init__(self, app) + + def getBrailleGenerator(self): + """Returns the braille generator for this script. + """ + return None + + def getSpeechGenerator(self): + """Returns the speech generator for this script. + """ + return None + + def processObjectEvent(self, event): + """Does nothing. + + Arguments: + - event: the Event + """ + pass + + def processBrailleEvent(self, brailleEvent): + """Does nothing. + + Arguments: + - brailleEvent: an instance of input_event.BrailleEvent + + Returns False to indicate the event was not consumed. + """ + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/__init__.py new file mode 100644 index 0000000..241725e --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Sleep mode script for Cthulhu.""" + +from .script import Script, getScript + +# Ensure getScript is available at module level +__all__ = ['Script', 'getScript'] \ No newline at end of file diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script.py new file mode 100644 index 0000000..c118105 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Script for sleep mode where Cthulhu ignores events and commands.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2024 Stormux" +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.scripts.default as default +import cthulhu.input_event as input_event +import cthulhu.keybindings as keybindings +import cthulhu.messages as messages +import cthulhu.script_manager as script_manager +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_scriptManager = script_manager.getManager() + +class Script(default.Script): + """The sleep-mode script.""" + + def __init__(self, app): + super().__init__(app) + self.presentIfInactive = True + + def activate(self): + """Called when this script is activated.""" + tokens = ["SLEEP MODE: Activating script for", self.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # Only keep the sleep mode toggle binding active + self.removeKeyGrabs() + self.addKeyGrabs() + + # Present sleep mode status + self.clearBraille() + app_name = AXObject.get_name(self.app) if self.app else "unknown application" + message = messages.SLEEP_MODE_ENABLED_FOR % app_name + self.presentMessage(message) + + def deactivate(self): + """Called when this script is deactivated.""" + tokens = ["SLEEP MODE: De-activating script for", self.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.removeKeyGrabs() + + def getKeyBindings(self): + """Only provide the key binding needed to exit sleep mode.""" + keyBindings = keybindings.KeyBindings() + + keyBindings.load([("q", keybindings.defaultModifierMask, + keybindings.CTHULHU_CTRL_ALT_MODIFIER_MASK | keybindings.SHIFT_ALT_MODIFIER_MASK, + "toggleSleepModeHandler")], + self.inputEventHandlers) + return keyBindings + + def setupInputEventHandlers(self): + """Sets up the input event handlers for sleep mode.""" + super().setupInputEventHandlers() + self.inputEventHandlers["toggleSleepModeHandler"] = \ + input_event.InputEventHandler( + Script.toggleSleepMode, + "Toggles sleep mode on/off") + + def toggleSleepMode(self, input_event=None): + """Toggles between sleep mode and regular mode.""" + script_manager = _scriptManager + script_manager.setActiveScript(script_manager.getDefaultScript(), "Sleep mode toggled") + self.presentMessage(messages.SLEEP_MODE_DISABLED_FOR % AXObject.get_name(self.app)) + return True + + def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): + """Handles changes of focus of interest to the script.""" + tokens = ["SLEEP MODE: focus changed from", oldLocusOfFocus, "to", newLocusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if oldLocusOfFocus is None and AXUtilities.is_application(AXObject.get_parent(newLocusOfFocus)): + self.clearBraille() + self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app)) + return + + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def presentKeyboardEvent(self, event): + """Prevents keyboard echo in sleep mode.""" + msg = "SLEEP MODE: Not presenting keyboard event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + def updateBraille(self, obj, **args): + """Don't update braille in sleep mode.""" + msg = "SLEEP MODE: Not updating braille." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # Event handler overrides - all do nothing + def onActiveChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onActiveDescendantChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onBusyChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onCaretMoved(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onCheckedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onChildrenAdded(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onChildrenRemoved(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onColumnReordered(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onDocumentLoadComplete(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onDocumentLoadStopped(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onDocumentReload(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onExpandedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onFocus(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onFocusedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onMouseButton(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onNameChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onSelectedChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onSelectionChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onShowingChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextAttributesChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextDeleted(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextInserted(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onTextSelectionChanged(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + self.clearBraille() + self.presentMessage(messages.SLEEP_MODE_ENABLED_FOR % AXObject.get_name(self.app)) + + def onWindowDeactivated(self, event): + msg = "SLEEP MODE: Ignoring event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + +def getScript(app): + """Returns the script for the given application.""" + return Script(app) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script_utilities.py new file mode 100644 index 0000000..13c5ee5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/sleepmode/script_utilities.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for Sleep Mode. Helps ensure we do nothing. When nothing is done, nothing is left undone.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2024 Stormux" +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities + +class Utilities(script_utilities.Utilities): + """Utilities class for the sleep-mode script.""" + + def willEchoCharacter(self, event): + """Returns True if we'll echo this character.""" + + msg = "SLEEP MODE: Will not echo character." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def displayRegionChanged(self, obj, start, end, mode): + """Don't track changes in sleep mode.""" + + msg = "SLEEP MODE: Will not track display changes." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def shouldPresentContext(self): + """Don't present context in sleep mode.""" + + msg = "SLEEP MODE: Will not present context." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/__init__.py new file mode 100644 index 0000000..1a92748 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/__init__.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for basic switchers like Metacity.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script +from .script_utilities import Utilities diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script.py new file mode 100644 index 0000000..4c8ae34 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for basic switchers like Metacity.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2019 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu import debug +from cthulhu import cthulhu +from cthulhu.scripts import default + +from .script_utilities import Utilities + + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for the given application.""" + + super().__init__(app) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def forceScriptActivation(self, event): + """Allows scripts to insist that they should become active.""" + + if self.utilities.isSwitcherSelectionChangeEventType(event): + return True + + return super().forceScriptActivation(event) + + def _handleSwitcherEvent(self, event): + """Presents the currently selected item, if appropriate.""" + + if not self.utilities.isSwitcherContainer(event.source): + msg = "SWITCHER: Event is not from switcher container" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not self.utilities.isSwitcherSelectionChangeEventType(event): + msg = "SWITCHER: Not treating event as selection change." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "SWITCHER: Treating event as selection change" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.presentationInterrupt() + cthulhu.setActiveWindow(self.utilities.topLevelObject(event.source)) + cthulhu.setLocusOfFocus(event, event.source, False) + self.presentMessage(self.utilities.getSelectionName(event.source), + resetStyles=False, force=True) + return True + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onFocusedChanged(event) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if self._handleSwitcherEvent(event): + return + + super().onNameChanged(event) + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onSelectedChanged(event) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onSelectionChanged(event) + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onShowingChanged(event) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onCaretMoved(event) + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onTextDeleted(event) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if self._handleSwitcherEvent(event): + return + + super().onTextInserted(event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script_utilities.py new file mode 100644 index 0000000..90a870f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/switcher/script_utilities.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2019 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import debug +from cthulhu import script_utilities +from cthulhu.ax_object import AXObject + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + super().__init__(script) + + def isSwitcherContainer(self, obj): + """Returns True if obj is the switcher container.""" + + return obj and AXObject.get_role(obj) == Atspi.Role.STATUS_BAR + + def isSwitcherSelectionChangeEventType(self, event): + """Returns True if this event is the one we use to present changes.""" + + if event.type.startswith("object:text-changed:insert"): + return True + + if event.type.startswith("object:state-changed:showing"): + return event.detail1 + + return False + + def getSelectionName(self, container): + """Returns the name of the currently-selected item.""" + + if self.isSwitcherContainer(container): + return AXObject.get_name(container) + + return "" + + def isZombie(self, obj): + if not super().isZombie(obj): + return False + + if AXObject.get_index_in_parent(obj) >= 0: + return True + + AXObject.clear_cache(obj) + + if self.isShowingAndVisible(obj): + tokens = ["SWITCHER: Ignoring bad index of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["SWITCHER:", obj, "has bad index and isn't showing and visible"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/__init__.py new file mode 100644 index 0000000..2eb914f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .braille_generator import BrailleGenerator +from .script import Script +from .speech_generator import SpeechGenerator +from .script_utilities import Utilities + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/braille_generator.py new file mode 100644 index 0000000..fb51d18 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/braille_generator.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu import braille_generator + + +class BrailleGenerator(braille_generator.BrailleGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateDescription(self, obj, **args): + # The text in the description is the same as the text in the page + # tab and similar to (and sometimes the same as) the prompt. + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script.py new file mode 100644 index 0000000..055c732 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu import debug +from cthulhu import cthulhu +from cthulhu.scripts import default + +from .braille_generator import BrailleGenerator +from .speech_generator import SpeechGenerator +from .script_utilities import Utilities + + +class Script(default.Script): + + def __init__(self, app): + super().__init__(app) + self.presentIfInactive = False + + def deactivate(self): + """Called when this script is deactivated.""" + + self.utilities.clearCache() + super().deactivate() + + def getBrailleGenerator(self): + """Returns the braille generator for this script.""" + + return BrailleGenerator(self) + + def getSpeechGenerator(self): + """Returns the speech generator for this script.""" + + return SpeechGenerator(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # https://bugzilla.gnome.org/show_bug.cgi?id=748311 + cthulhu.setLocusOfFocus(event, event.source) + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if self.utilities.treatEventAsNoise(event): + msg = "TERMINAL: Deletion is believed to be noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().onTextDeleted(event) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if not self.utilities.treatEventAsCommand(event): + msg = "TERMINAL: Passing along event to default script." + debug.printMessage(debug.LEVEL_INFO, msg, True) + super().onTextInserted(event) + return + + msg = "TERMINAL: Insertion is believed to be due to terminal command" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.updateBraille(event.source) + + newString = self.utilities.insertedText(event) + if len(newString) == 1: + self.speakCharacter(newString) + else: + voice = self.speechGenerator.voice(obj=event.source, string=newString) + self.speakMessage(newString, voice=voice) + + if self.flatReviewPresenter.is_active(): + msg = "TERMINAL: Flat review presenter is active. Ignoring insertion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + try: + text = event.source.queryText() + except Exception: + pass + else: + self._saveLastCursorPosition(event.source, text.caretOffset) + self.utilities.updateCachedTextSelection(event.source) + + def presentKeyboardEvent(self, event): + if not event.isPrintableKey(): + return super().presentKeyboardEvent(event) + + if event.isPressedKey(): + return False + + self._sayAllIsInterrupted = False + self.utilities.clearCachedCommandState() + if not event.shouldEcho or event.isCthulhuModified() or event.isCharacterEchoable(): + return False + + # We have no reliable way of knowing a password is being entered into + # a terminal -- other than the fact that the text typed isn't there. + try: + text = event.getObject().queryText() + offset = text.caretOffset + prevChar = text.getText(offset - 1, offset) + char = text.getText(offset, offset + 1) + except Exception: + return False + + string = event.event_string + if string not in [prevChar, "space", char]: + return False + + tokens = ["TERMINAL: Presenting keyboard event", string] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.speakKeyEvent(event) + return True + + def skipObjectEvent(self, event): + if event.type == "object:text-changed:insert": + return False + + newEvent, newTime = None, 0 + if event.type == "object:text-changed:delete": + if self.utilities.isBackSpaceCommandTextDeletionEvent(event): + return False + + newEvent, newTime = self.eventCache.get("object:text-changed:insert", [None, 0]) + + if newEvent is None or newEvent.source != event.source: + return super().skipObjectEvent(event) + + if event.detail1 != newEvent.detail1: + return False + + data = "\n%s%s" % (" " * 11, str(newEvent).replace("\t", " " * 11)) + tokens = ["TERMINAL: Skipping due to more recent event at offset", data] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script_utilities.py new file mode 100644 index 0000000..ed31327 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/script_utilities.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import re + +from cthulhu import debug +from cthulhu import keybindings +from cthulhu import cthulhu_state +from cthulhu import script_utilities +from cthulhu import settings_manager +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + super().__init__(script) + + def clearCache(self): + pass + + def deletedText(self, event): + match = re.search("\n~", event.any_data) + if not match: + return event.any_data + + adjusted = event.any_data[:match.start()] + tokens = ["TERMINAL: Adjusted deletion: '", adjusted, "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return adjusted + + def insertedText(self, event): + if len(event.any_data) == 1: + return event.any_data + + if self.isAutoTextEvent(event): + return event.any_data + + if self.isClipboardTextChangedEvent(event): + return event.any_data + + try: + text = event.source.queryText() + except Exception: + tokens = ["ERROR: Exception querying text for", event.source] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return event.any_data + + start, end = event.detail1, event.detail1 + len(event.any_data) + boundary = Atspi.TextBoundaryType.LINE_START + + firstLine = text.getTextAtOffset(start, boundary) + tokens = ["TERMINAL: First line of insertion:", firstLine] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + lastLine = text.getTextAtOffset(end - 1, boundary) + tokens = ["TERMINAL: Last line of insertion:", firstLine] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if firstLine == lastLine: + msg = "TERMINAL: Not adjusting single-line insertion." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return event.any_data + + currentLine = text.getTextAtOffset(text.caretOffset, boundary) + tokens = ["TERMINAL: Current line:", firstLine] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if firstLine != ("", 0, 0): + start = firstLine[1] + + if currentLine not in (("", 0, 0), firstLine, lastLine): + lastLine = currentLine + + if lastLine != ("", 0, 0): + end = lastLine[2] + if lastLine[0].endswith("\n"): + end -= 1 + + adjusted = text.getText(start, end) + if adjusted: + tokens = ["TERMINAL: Adjusted insertion: '", adjusted, "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + msg = "TERMINAL: Adjustment failed. Returning any_data." + debug.printMessage(debug.LEVEL_INFO, msg, True) + adjusted = event.any_data + + return adjusted + + def insertionEndsAtCaret(self, event): + try: + text = event.source.queryText() + except Exception: + tokens = ["ERROR: Exception querying text for", event.source] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return text.caretOffset == event.detail1 + event.detail2 + + def isEditableTextArea(self, obj): + if AXUtilities.is_terminal(obj): + return True + + return super().isEditableTextArea(obj) + + def isTextArea(self, obj): + if AXUtilities.is_terminal(obj): + return True + + return super().isTextArea(obj) + + def isAutoTextEvent(self, event): + if not event.type.startswith("object:text-changed:insert"): + return False + + if not event.any_data or not event.source: + return False + + if len(event.any_data) <= 1: + return False + + lastKey, mods = self.lastKeyAndModifiers() + if lastKey == "Tab": + return event.any_data != "\t" + if lastKey == "Return" and event.any_data.startswith("\n"): + return event.any_data.strip() and not event.any_data.count("\n~") + + return False + + def lastInputEventWasCopy(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'c' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return mods & keybindings.SHIFT_MODIFIER_MASK + + return False + + def lastInputEventWasPaste(self): + keycode, mods = self._lastKeyCodeAndModifiers() + keynames = self._allNamesForKeyCode(keycode) + if 'v' not in keynames: + return False + + if mods & keybindings.CTRL_MODIFIER_MASK: + return mods & keybindings.SHIFT_MODIFIER_MASK + + return False + + def treatEventAsCommand(self, event): + if event.source != cthulhu_state.locusOfFocus: + return False + + if event.type.startswith("object:text-changed:insert") and event.any_data.strip(): + # To let default script handle presentation. + if self.lastInputEventWasPaste(): + return False + + if event.any_data.count("\n~"): + return False + + keyString, mods = self.lastKeyAndModifiers() + if keyString in ["Return", "Tab", "space", " "]: + return re.search(r"[^\d\s]", event.any_data) + if mods & keybindings.ALT_MODIFIER_MASK: + return True + if self.lastInputEventWasPrintableKey(): + return len(event.any_data) > 1 + if self.insertionEndsAtCaret(event): + return True + + return False + + def treatEventAsNoise(self, event): + if self.lastInputEventWasCommand(): + return False + + if event.type.startswith("object:text-changed:delete") and event.any_data.strip(): + keyString, mods = self.lastKeyAndModifiers() + if keyString in ["Return", "Tab", "space", " "]: + return True + if mods & keybindings.ALT_MODIFIER_MASK: + return True + if len(event.any_data) > 1 and self.lastInputEventWasPrintableKey(): + return True + + return False + + def willEchoCharacter(self, event): + if not _settingsManager.getSetting("enableEchoByCharacter"): + return False + + if len(event.event_string) != 1 \ + or event.modifiers & keybindings.CTHULHU_CTRL_MODIFIER_MASK: + return False + + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/speech_generator.py new file mode 100644 index 0000000..7f948d9 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/terminal/speech_generator.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu import speech_generator + + +class SpeechGenerator(speech_generator.SpeechGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateDescription(self, obj, **args): + # The text in the description is the same as the text in the page + # tab and similar to (and sometimes the same as) the prompt. + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/__init__.py new file mode 100644 index 0000000..82fc251 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Chromium.""" + +# https://gitlab.gnome.org/GNOME/cthulhu/-/issues/358 +# ruff: noqa: F401 +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/braille_generator.py new file mode 100644 index 0000000..a8ba75f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/braille_generator.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom braille generator for Chromium.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2018-2019 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import debug +from cthulhu.scripts import web +from cthulhu.ax_object import AXObject + + +class BrailleGenerator(web.BrailleGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateLabelOrName(self, obj, **args): + if AXObject.get_role(obj) == Atspi.Role.FRAME: + document = self._script.utilities.activeDocument(obj) + if document and not self._script.utilities.documentFrameURI(document): + # Eliminates including "untitled" in the frame name. + return super()._generateLabelOrName(AXObject.get_parent(obj)) + + return super()._generateLabelOrName(obj) + + def generateBraille(self, obj, **args): + if self._script.utilities.inDocumentContent(obj): + return super().generateBraille(obj, **args) + + oldRole = None + if self._script.utilities.treatAsMenu(obj): + tokens = ["CHROMIUM: HACK? Displaying menu item as menu", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + oldRole = self._overrideRole(Atspi.Role.MENU, args) + + result = super().generateBraille(obj, **args) + if oldRole is not None: + self._restoreRole(oldRole, args) + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script.py new file mode 100644 index 0000000..45ed7d1 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script.py @@ -0,0 +1,468 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for Chromium.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2018-2019 Igalia, S.L." +__license__ = "LGPL" + +from cthulhu import debug +from cthulhu import cthulhu +from cthulhu import cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities +from cthulhu.scripts import default +from cthulhu.scripts import web +from .braille_generator import BrailleGenerator +from .script_utilities import Utilities +from .speech_generator import SpeechGenerator + + +class Script(web.Script): + + def __init__(self, app): + super().__init__(app) + + self.presentIfInactive = False + + def getBrailleGenerator(self): + """Returns the braille generator for this script.""" + + return BrailleGenerator(self) + + def getSpeechGenerator(self): + """Returns the speech generator for this script.""" + + return SpeechGenerator(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def isActivatableEvent(self, event): + """Returns True if this event should activate this script.""" + + if event.type == "window:activate": + return self.utilities.canBeActiveWindow(event.source) + + return super().isActivatableEvent(event) + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if super().locusOfFocusChanged(event, oldFocus, newFocus): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.locusOfFocusChanged(self, event, oldFocus, newFocus) + + def onActiveChanged(self, event): + """Callback for object:state-changed:active accessibility events.""" + + if super().onActiveChanged(event): + return + + if event.detail1 and AXUtilities.is_frame(event.source) \ + and not self.utilities.canBeActiveWindow(event.source): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onActiveChanged(self, event) + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if super().onActiveDescendantChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onActiveDescendantChanged(self, event) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + + if self.utilities.hasNoSize(event.source): + msg = "CHROMIUM: Ignoring event from page with no size." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if not self.utilities.documentFrameURI(event.source): + msg = "CHROMIUM: Ignoring event from page with no URI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onBusyChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onBusyChanged(self, event) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if self.utilities.isStaticTextLeaf(event.source): + msg = "CHROMIUM: Ignoring event from static-text leaf" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.utilities.isRedundantAutocompleteEvent(event): + msg = "CHROMIUM: Ignoring redundant autocomplete event" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onCaretMoved(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onCaretMoved(self, event) + + def onCheckedChanged(self, event): + """Callback for object:state-changed:checked accessibility events.""" + + if super().onCheckedChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onCheckedChanged(self, event) + + def onColumnReordered(self, event): + """Callback for object:column-reordered accessibility events.""" + + if super().onColumnReordered(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onColumnReordered(self, event) + + def onChildrenAdded(self, event): + """Callback for object:children-changed:add accessibility events.""" + + if self.utilities.isStaticTextLeaf(event.any_data): + msg = "CHROMIUM: Ignoring because child is static text leaf" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onChildrenAdded(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onChildrenAdded(self, event) + + def onChildrenRemoved(self, event): + """Callback for object:children-changed:removed accessibility events.""" + + if self.utilities.isStaticTextLeaf(event.any_data): + msg = "CHROMIUM: Ignoring because child is static text leaf" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onChildrenRemoved(event): + return + + msg = "Chromium: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onChildrenRemoved(self, event) + + def onDocumentLoadComplete(self, event): + """Callback for document:load-complete accessibility events.""" + + if not self.utilities.documentFrameURI(event.source): + msg = "CHROMIUM: Ignoring event from page with no URI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onDocumentLoadComplete(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onDocumentLoadComplete(self, event) + + def onDocumentLoadStopped(self, event): + """Callback for document:load-stopped accessibility events.""" + + if not self.utilities.documentFrameURI(event.source): + msg = "CHROMIUM: Ignoring event from page with no URI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onDocumentLoadStopped(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onDocumentLoadStopped(self, event) + + def onDocumentReload(self, event): + """Callback for document:reload accessibility events.""" + + if not self.utilities.documentFrameURI(event.source): + msg = "CHROMIUM: Ignoring event from page with no URI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onDocumentReload(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onDocumentReload(self, event) + + def onExpandedChanged(self, event): + """Callback for object:state-changed:expanded accessibility events.""" + + if super().onExpandedChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onExpandedChanged(self, event) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # This event is deprecated. We should get object:state-changed:focused + # events instead. + + if super().onFocus(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onFocus(self, event) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if self.utilities.isDocument(event.source) \ + and not self.utilities.documentFrameURI(event.source): + msg = "CHROMIUM: Ignoring event from document with no URI." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onFocusedChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onFocusedChanged(self, event) + + def onMouseButton(self, event): + """Callback for mouse:button accessibility events.""" + + if super().onMouseButton(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onMouseButton(self, event) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if super().onNameChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onNameChanged(self, event) + + def onRowReordered(self, event): + """Callback for object:row-reordered accessibility events.""" + + if super().onRowReordered(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onRowReordered(self, event) + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + if super().onSelectedChanged(event): + return + + if event.detail1 and not self.utilities.inDocumentContent(event.source): + # The popup for an input with autocomplete on is a listbox child of a nameless frame. + # It lives outside of the document and also doesn't fire selection-changed events. + if listbox := AXObject.get_parent(event.source, AXUtilities.is_list_box): + parent = AXObject.get_parent(listbox) + if AXUtilities.is_frame(parent) and not AXObject.get_name(parent): + msg = "CHROMIUM: Event source believed to be in autocomplete popup" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu_state.locusOfFocus = event.source + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onSelectedChanged(self, event) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if super().onSelectionChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onSelectionChanged(self, event) + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + if event.detail1 and self.utilities.isMenuWithNoSelectedChild(event.source): + topLevel = self.utilities.topLevelObject(event.source) + if self.utilities.canBeActiveWindow(topLevel): + cthulhu.setActiveWindow(topLevel) + self.presentObject(event.source) + cthulhu.setLocusOfFocus(event, event.source, False) + return + + if super().onShowingChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onShowingChanged(self, event) + + def onTextAttributesChanged(self, event): + """Callback for object:text-attributes-changed accessibility events.""" + + if super().onTextAttributesChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextAttributesChanged(self, event) + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if super().onTextDeleted(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextDeleted(self, event) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if super().onTextInserted(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextInserted(self, event) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + if self.utilities.isStaticTextLeaf(event.source): + msg = "CHROMIUM: Ignoring event from static-text leaf" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.utilities.isListItemMarker(event.source): + msg = "CHROMIUM: Ignoring event from list item marker" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onTextSelectionChanged(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextSelectionChanged(self, event) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + if not self.utilities.canBeActiveWindow(event.source): + return + + # If this is a frame for a popup menu, we don't want to treat + # it like a proper window:activate event because it's not as + # far as the end-user experience is concerned. + menu = self.utilities.popupMenuForFrame(event.source) + if menu: + cthulhu.setActiveWindow(event.source) + + activeItem = None + selected = self.utilities.selectedChildren(menu) + if len(selected) == 1: + activeItem = selected[0] + + if activeItem: + # If this is the popup menu for the locusOfFocus, we don't want to + # present the popup menu as part of the new ancestry of activeItem. + if self.utilities.isPopupMenuForCurrentItem(menu): + cthulhu.setLocusOfFocus(event, menu, False) + + tokens = ["CHROMIUM: Setting locusOfFocus to active item", activeItem] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, activeItem) + return + + tokens = ["CHROMIUM: Setting locusOfFocus to popup menu", menu] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, menu) + + if super().onWindowActivated(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onWindowActivated(self, event) + + # Right now we don't get accessibility events for alerts which are + # already showing at the time of window activation. If that changes, + # we should store presented alerts so we don't double-present them. + for child in AXObject.iter_children(event.source): + if AXUtilities.is_alert(child): + self.presentObject(child) + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + if super().onWindowDeactivated(event): + return + + msg = "CHROMIUM: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onWindowDeactivated(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script_utilities.py new file mode 100644 index 0000000..5c8793b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/script_utilities.py @@ -0,0 +1,438 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script utilities for Chromium""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2018-2019 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +import re + +from cthulhu import debug +from cthulhu import cthulhu_state +from cthulhu.scripts import web +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(web.Utilities): + + def __init__(self, script): + super().__init__(script) + self._isStaticTextLeaf = {} + self._isPseudoElement = {} + self._isListItemMarker = {} + self._topLevelObject = {} + + def clearCachedObjects(self): + super().clearCachedObjects() + self._isStaticTextLeaf = {} + self._isPseudoElement = {} + self._isListItemMarker = {} + self._topLevelObject = {} + + def isStaticTextLeaf(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isStaticTextLeaf(obj) + + if AXObject.get_child_count(obj): + return False + + if self.isListItemMarker(obj): + return False + + rv = self._isStaticTextLeaf.get(hash(obj)) + if rv is not None: + return rv + + roles = [Atspi.Role.STATIC, Atspi.Role.TEXT] + rv = AXObject.get_role(obj) in roles and self._getTag(obj) in (None, "", "br") + if rv: + tokens = ["CHROMIUM:", obj, "believed to be static text leaf"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._isStaticTextLeaf[hash(obj)] = rv + return rv + + def isPseudoElement(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isPseudoElement(obj) + + rv = self._isPseudoElement.get(hash(obj)) + if rv is not None: + return rv + + rv = self._getTag(obj) in ["", ""] + if rv: + tokens = ["CHROMIUM:", obj, "believed to be pseudo element"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._isPseudoElement[hash(obj)] = rv + return rv + + def isListItemMarker(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isListItemMarker.get(hash(obj)) + if rv is not None: + return rv + + rv = False + parent = AXObject.get_parent(obj) + if AXUtilities.is_list_item(parent): + tag = self._getTag(obj) + if tag == "::marker": + rv = True + elif tag: + rv = False + elif AXObject.get_child_count(parent) > 1: + rv = AXObject.get_child(parent, 0) == obj + else: + rv = AXObject.get_name(obj) != self.displayedText(parent) + + self._isListItemMarker[hash(obj)] = rv + return rv + + def isMenuInCollapsedSelectElement(self, obj): + if not AXUtilities.is_menu(obj): + return False + + parent = AXObject.get_parent(obj) + if self._getTag(parent) != 'select': + return False + + return not AXUtilities.is_expanded(parent) + + def treatAsMenu(self, obj): + # Unlike other apps and toolkits, submenus in Chromium have the menu item + # role rather than the menu role, but we can identify them as submenus via + # the has-popup state. + return AXUtilities.is_menu_item(obj) and AXUtilities.has_popup(obj) + + def isPopupMenuForCurrentItem(self, obj): + # When a submenu is closed, it has role menu item. But when that submenu + # is opened/expanded, a menu with that same name appears. It would be + # nice if there were a connection (parent/child or an accessible relation) + # between the two.... + return self.treatAsMenu(cthulhu_state.locusOfFocus) and super().isPopupMenuForCurrentItem(obj) + + def isFrameForPopupMenu(self, obj): + # The ancestry of a popup menu appears to be a menu bar (even though + # one is not actually showing) contained in a nameless frame. It would + # be nice if these things were pruned from the accessibility tree.... + if not AXUtilities.is_frame(obj): + return False + if AXObject.get_name(obj): + return False + if AXObject.get_child_count(obj) != 1: + return False + return AXUtilities.is_menu_bar(AXObject.get_child(obj, 0)) + + def isTopLevelMenu(self, obj): + return AXUtilities.is_menu(obj) and self.isFrameForPopupMenu(self.topLevelObject(obj)) + + def popupMenuForFrame(self, obj): + if not self.isFrameForPopupMenu(obj): + return None + + menu = AXObject.find_descendant(obj, AXUtilities.is_menu) + tokens = ["CHROMIUM: Popup menu for", obj, ":", menu] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return menu + + def topLevelObject(self, obj, useFallbackSearch=False): + if not obj: + return None + + result = super().topLevelObject(obj) + if AXObject.get_role(result) in self._topLevelRoles(): + if not self.isFindContainer(result): + return result + else: + parent = AXObject.get_parent(result) + tokens = ["CHROMIUM: Top level object for", obj, "is", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return parent + + cached = self._topLevelObject.get(hash(obj)) + if cached is not None: + return cached + + tokens = ["CHROMIUM: WARNING: Top level object for", obj, "is", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # The only (known) object giving us a broken ancestry is the omnibox popup. + if not (AXUtilities.is_list_item(obj or AXUtilities.is_list_box(obj))): + return result + + listbox = obj + if AXUtilities.is_list_item(obj): + listbox = AXObject.get_parent(listbox) + + if listbox is None: + return result + + # The listbox sometimes claims to be a redundant object rather than a listbox. + # Clearing the AT-SPI2 cache seems to be the trigger. + if not AXUtilities.is_list_box(listbox): + if AXUtilities.is_redundant_object(listbox): + tokens = ["CHROMIUM: WARNING: Suspected bogus role on listbox", listbox] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + return result + + autocomplete = self.autocompleteForPopup(listbox) + if autocomplete: + result = self.topLevelObject(autocomplete) + tokens = ["CHROMIUM: Top level object for", autocomplete, "is", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._topLevelObject[hash(obj)] = result + return result + + def autocompleteForPopup(self, obj): + relation = AXObject.get_relation(obj, Atspi.RelationType.POPUP_FOR) + if not relation: + return None + + target = relation.get_target(0) + if AXUtilities.is_autocomplete(target): + return target + + return None + + def isBrowserAutocompletePopup(self, obj): + if not obj or self.inDocumentContent(obj): + return False + + return self.autocompleteForPopup(obj) is not None + + def isRedundantAutocompleteEvent(self, event): + if not AXUtilities.is_autocomplete(event.source): + return False + + if event.type.startswith("object:text-caret-moved"): + lastKey, mods = self.lastKeyAndModifiers() + if lastKey in ["Down", "Up"]: + return True + + return False + + def setCaretPosition(self, obj, offset, documentFrame=None): + super().setCaretPosition(obj, offset, documentFrame) + + link = AXObject.find_ancestor(obj, AXUtilities.is_link) + if link is not None: + tokens = ["CHROMIUM: HACK: Grabbing focus on", obj, "'s ancestor", link] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.grabFocus(link) + + def handleAsLiveRegion(self, event): + if not super().handleAsLiveRegion(event): + return False + + if not event.type.startswith("object:children-changed:add"): + return True + + # At least some of the time, we're getting text insertion events immediately + # followed by children-changed events to tell us that the object whose text + # changed is now being added to the accessibility tree. Furthermore the + # additions are not always coming to us in presentational order, whereas + # the text changes appear to be. So most of the time, we can ignore the + # children-changed events. Except for when we can't. + if AXUtilities.is_table(event.any_data): + return True + + msg = "CHROMIUM: Event is believed to be redundant live region notification" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def getFindResultsCount(self, root=None): + root = root or self._findContainer + if not root: + return "" + + statusBars = AXUtilities.find_all_status_bars(root) + if len(statusBars) != 1: + return "" + + bar = statusBars[0] + AXObject.clear_cache(bar) + if len(re.findall(r"\d+", AXObject.get_name(bar))) == 2: + return AXObject.get_name(bar) + + return "" + + def isFindContainer(self, obj): + if not obj or self.inDocumentContent(obj): + return False + + if obj == self._findContainer: + return True + + if not AXUtilities.is_dialog(obj): + return False + + result = self.getFindResultsCount(obj) + if result: + tokens = ["CHROMIUM:", obj, "believed to be find-in-page container (", result, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._findContainer = obj + return True + + # When there are no results due to the absence of a search term, the status + # bar lacks a name. When there are no results due to lack of match, the name + # of the status bar is "No results" (presumably localized). Therefore fall + # back on the widgets. TODO: This would be far easier if Chromium gave us an + # object attribute we could look for.... + + if len(AXUtilities.find_all_entries(obj)) != 1: + tokens = ["CHROMIUM:", obj, "not believed to be find-in-page container (entry count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if len(AXUtilities.find_all_push_buttons(obj)) != 3: + tokens = ["CHROMIUM:", obj, "not believed to be find-in-page container (button count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if len(AXUtilities.find_all_separators(obj)) != 1: + tokens = ["CHROMIUM:", obj, + "not believed to be find-in-page container (separator count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["CHROMIUM:", obj, "believed to be find-in-page container (accessibility tree)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._findContainer = obj + return True + + def inFindContainer(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + if not (AXUtilities.is_entry(obj) or AXUtilities.is_push_button(obj)): + return False + if self.inDocumentContent(obj): + return False + + result = self.isFindContainer(AXObject.find_ancestor(obj, AXUtilities.is_dialog)) + if result: + tokens = ["CHROMIUM:", obj, "believed to be find-in-page widget"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return result + + def isHidden(self, obj): + if not super().isHidden(obj): + return False + + if self.isMenuInCollapsedSelectElement(obj): + return False + + return True + + def findAllDescendants(self, root, includeIf=None, excludeIf=None): + if not root: + return [] + + # Don't bother if the root is a 'pre' or 'code' element. Those often have + # nothing but a TON of static text leaf nodes, which we want to ignore. + if self._getTag(root) in ('pre', 'code'): + tokens = ["CHROMIUM: Returning 0 descendants for pre/code", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + return super().findAllDescendants(root, includeIf, excludeIf) + + def accessibleAtPoint(self, root, x, y, coordType=None): + result = super().accessibleAtPoint(root, x, y, coordType) + + # Chromium cannot do a hit test of web content synchronously. So what it + # does is return a guess, then fire off an async hit test. The next time + # one calls it, Chromium returns the previous async hit test result if + # the point is still within its bounds. Therefore, we need to call + # accessibleAtPoint() twice to be safe. + msg = "CHROMIUM: Getting accessibleAtPoint again due to async hit test result." + debug.printMessage(debug.LEVEL_INFO, msg, True) + result = super().accessibleAtPoint(root, x, y, coordType) + return result + + def _isActiveAndShowingAndNotIconified(self, obj): + if super()._isActiveAndShowingAndNotIconified(obj): + return True + + if obj and AXObject.get_application(obj) != self._script.app: + return False + + # FIXME: This can potentially be non-performant because AT-SPI2 will recursively + # clear the cache of all descendants. This is an attempt to work around what may + # be a lack of window:activate and object:state-changed events from Chromium + # windows in at least some environments. + try: + tokens = ["CHROMIUM: Clearing cache for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + AXObject.clear_cache(obj) + except Exception: + tokens = ["CHROMIUM: Exception clearing cache for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if super()._isActiveAndShowingAndNotIconified(obj): + tokens = ["CHROMIUM:", obj, "deemed to be active and showing after cache clear"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def _shouldCalculatePositionAndSetSize(self, obj): + # Chromium calculates posinset and setsize for description lists based on the + # number of terms present. If we want to present the number of values associated + # with a given term, we need to work those values out ourselves. + if self.isDescriptionListDescription(obj): + return True + + if self.inDocumentContent(obj): + return super()._shouldCalculatePositionAndSetSize(obj) + + # Chromium has accessible menu items which are not focusable and therefore do not + # have a posinset and setsize calculated. But they may claim to be the selected + # item when an accessible child is selected (e.g. "zoom" when "+" or "-" gains focus. + # Normally we calculate posinset and setsize when the application hasn't provided it. + # We don't want to do that in the case of menu items like "zoom" because our result + # will not jibe with the values of its siblings. Thus if a sibling has a value, + # assume that the missing attributes are missing on purpose. + for sibling in AXObject.iter_children(AXObject.get_parent(obj)): + if self.getPositionInSet(sibling) is not None: + tokens = ["CHROMIUM:", obj, "'s sibling", sibling, "has posinset."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/speech_generator.py new file mode 100644 index 0000000..f5b4e97 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Chromium/speech_generator.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom speech generator for Chromium.""" + +# Please note: ATK support in Chromium needs much work. Until that work has been +# done, Cthulhu will not be able to provide access to Chromium. This generator is a +# work in progress. + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2018-2019 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import debug +from cthulhu.scripts import web +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class SpeechGenerator(web.SpeechGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateNewAncestors(self, obj, **args): + # Likely a refocused submenu whose functional child was just collapsed. + # The new ancestors might technically be new, but they are not as far + # as the user is concerned. + if self._script.utilities.treatAsMenu(obj): + tokens = ["CHROMIUM: Not generating new ancestors for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + return super()._generateNewAncestors(obj, **args) + + def _generateListBoxItemWidgets(self, obj, **args): + # The list which descends from a combobox should be a menu, and its children + # menuitems. We can remove this once that change is made in Chromium. + if AXObject.find_ancestor(obj, AXUtilities.is_combo_box): + tokens = ["CHROMIUM: Not generating listbox item widgets for combobox child", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + return super()._generateListBoxItemWidgets(obj, **args) + + def _generateLabelOrName(self, obj, **args): + if AXUtilities.is_frame(obj): + document = self._script.utilities.activeDocument(obj) + if document and not self._script.utilities.documentFrameURI(document): + # Eliminates including "untitled" in the frame name. + return super()._generateLabelOrName(AXObject.get_parent(obj)) + + return super()._generateLabelOrName(obj, **args) + + def _generateRoleName(self, obj, **args): + if self._script.utilities.isListItemMarker(obj): + return [] + + return super()._generateRoleName(obj, **args) + + def generateSpeech(self, obj, **args): + if self._script.utilities.inDocumentContent(obj): + return super().generateSpeech(obj, **args) + + oldRole = None + if self._script.utilities.treatAsMenu(obj): + tokens = ["CHROMIUM: HACK? Speaking menu item as menu", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + oldRole = self._overrideRole(Atspi.Role.MENU, args) + + result = super().generateSpeech(obj, **args) + if oldRole is not None: + self._restoreRole(oldRole, args) + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script.py new file mode 100644 index 0000000..15d2226 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013-2014 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.default as default +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .script_utilities import Utilities + +class Script(default.Script): + + def __init__(self, app): + default.Script.__init__(self, app) + + def getUtilities(self): + return Utilities(self) + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if self.utilities.isInOpenMenuBarMenu(newFocus): + window = self.utilities.topLevelObject(newFocus) + windowChanged = window and cthulhu_state.activeWindow != window + if windowChanged: + cthulhu.setActiveWindow(window) + + super().locusOfFocusChanged(event, oldFocus, newFocus) + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if not self.utilities.isTypeahead(cthulhu_state.locusOfFocus): + super().onActiveDescendantChanged(event) + return + + msg = "GAIL: locusOfFocus believed to be typeahead. Presenting change." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.presentObject(event.any_data, interrupt=True) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # NOTE: This event type is deprecated and Cthulhu should no longer use it. + # This callback remains just to handle bugs in applications and toolkits + # that fail to reliably emit object:state-changed:focused events. + if self.utilities.isLayoutOnly(event.source): + return + + if self.utilities.isTypeahead(cthulhu_state.locusOfFocus) \ + and AXObject.supports_table(event.source) \ + and not AXUtilities.is_focused(event.source): + return + + ancestor = AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.source) + if not ancestor: + cthulhu.setLocusOfFocus(event, event.source) + return + + if AXObject.supports_table(ancestor): + return + + if AXUtilities.is_menu(ancestor) \ + and not AXObject.find_ancestor(ancestor, AXUtilities.is_menu): + return + + cthulhu.setLocusOfFocus(event, event.source) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + isFocused = AXUtilities.is_focused(event.source) + if not isFocused and self.utilities.isTypeahead(cthulhu_state.locusOfFocus): + msg = "GAIL: locusOfFocus believed to be typeahead. Presenting change." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + selectedChildren = self.utilities.selectedChildren(event.source) + for child in selectedChildren: + if not self.utilities.isLayoutOnly(child): + self.presentObject(child) + return + + if AXUtilities.is_layered_pane(event.source) \ + and self.utilities.selectedChildCount(event.source) > 1: + return + + super().onSelectionChanged(event) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + obj = event.source + if not self.utilities.isSameObject(obj, cthulhu_state.locusOfFocus): + return + + default.Script.onTextSelectionChanged(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script_utilities.py new file mode 100644 index 0000000..c04a533 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/GAIL/script_utilities.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import re + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + super().__init__(script) + self._isTypeahead = {} + self._isLayoutOnly = {} + + def clearCachedObjects(self): + self._isTypeahead = {} + self._isLayoutOnly = {} + + def isTypeahead(self, obj): + if not AXUtilities.is_text(obj): + return False + + rv = self._isTypeahead.get(hash(obj)) + if rv is not None: + return rv + + parent = AXObject.get_parent(obj) + while parent and self.isLayoutOnly(parent): + parent = AXObject.get_parent(parent) + + rv = AXUtilities.is_window(parent) + self._isTypeahead[hash(obj)] = rv + return rv + + def rgbFromString(self, attributeValue): + regex = re.compile(r"rgb|[^\w,]", re.IGNORECASE) + string = re.sub(regex, "", attributeValue) + red, green, blue = string.split(",") + + return int(red) >> 8, int(green) >> 8, int(blue) >> 8 + + def isLayoutOnly(self, obj): + rv = self._isLayoutOnly.get(hash(obj)) + if rv is not None: + if rv: + tokens = ["GTK:", obj, "is deemed to be layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + rv = super().isLayoutOnly(obj) + self._isLayoutOnly[hash(obj)] = rv + return rv diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/__init__.py new file mode 100644 index 0000000..1cc055f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/__init__.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script +from .script_utilities import Utilities diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script.py new file mode 100644 index 0000000..50325d5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010 Cthulhu Team." \ + "Copyright (c) 2014-2015 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import debug +from cthulhu import cthulhu +from cthulhu import cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.scripts import default +from cthulhu.scripts import web +from .script_utilities import Utilities + + +class Script(web.Script): + + def __init__(self, app): + super().__init__(app) + + self.presentIfInactive = False + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def isActivatableEvent(self, event): + if event.type == "window:activate": + return self.utilities.canBeActiveWindow(event.source) + + return super().isActivatableEvent(event) + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if super().locusOfFocusChanged(event, oldFocus, newFocus): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.locusOfFocusChanged(self, event, oldFocus, newFocus) + + def onActiveChanged(self, event): + """Callback for object:state-changed:active accessibility events.""" + + if super().onActiveChanged(event): + return + + if event.detail1 and AXObject.get_role(event.source) == Atspi.Role.FRAME \ + and not self.utilities.canBeActiveWindow(event.source): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onActiveChanged(self, event) + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if super().onActiveDescendantChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onActiveDescendantChanged(self, event) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + + if self.utilities.isNotRealDocument(event.source): + msg = "GECKO: Ignoring: Event source is not real document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onBusyChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onBusyChanged(self, event) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if super().onCaretMoved(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onCaretMoved(self, event) + + def onCheckedChanged(self, event): + """Callback for object:state-changed:checked accessibility events.""" + + if super().onCheckedChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onCheckedChanged(self, event) + + def onColumnReordered(self, event): + """Callback for object:column-reordered accessibility events.""" + + if super().onColumnReordered(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onColumnReordered(self, event) + + def onChildrenAdded(self, event): + """Callback for object:children-changed:add accessibility events.""" + + if super().onChildrenAdded(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onChildrenAdded(self, event) + + def onChildrenRemoved(self, event): + """Callback for object:children-changed:removed accessibility events.""" + + if super().onChildrenRemoved(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onChildrenRemoved(self, event) + + def onDocumentLoadComplete(self, event): + """Callback for document:load-complete accessibility events.""" + + if self.utilities.isNotRealDocument(event.source): + msg = "GECKO: Ignoring: Event source is not real document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if super().onDocumentLoadComplete(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onDocumentLoadComplete(self, event) + + def onDocumentLoadStopped(self, event): + """Callback for document:load-stopped accessibility events.""" + + if super().onDocumentLoadStopped(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onDocumentLoadStopped(self, event) + + def onDocumentReload(self, event): + """Callback for document:reload accessibility events.""" + + if super().onDocumentReload(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onDocumentReload(self, event) + + def onExpandedChanged(self, event): + """Callback for object:state-changed:expanded accessibility events.""" + + if super().onExpandedChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onExpandedChanged(self, event) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # This event is deprecated. We should get object:state-changed:focused + # events instead. + + if super().onFocus(event): + return + + if self.utilities.isLayoutOnly(event.source): + return + + if event.source == cthulhu_state.activeWindow: + msg = "GECKO: Ignoring event for active window." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + # NOTE: This event type is deprecated and Cthulhu should no longer use it. + # This callback remains just to handle bugs in applications and toolkits + # in which object:state-changed:focused events are missing. And in the + # case of Gecko dialogs, that seems to happen a lot. + cthulhu.setLocusOfFocus(event, event.source) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if super().onFocusedChanged(event): + return + + if AXObject.get_role(event.source) == Atspi.Role.PANEL: + if cthulhu_state.locusOfFocus == cthulhu_state.activeWindow: + msg = "GECKO: Ignoring event believed to be noise." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onFocusedChanged(self, event) + + def onMouseButton(self, event): + """Callback for mouse:button accessibility events.""" + + if super().onMouseButton(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onMouseButton(self, event) + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if super().onNameChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onNameChanged(self, event) + + def onRowReordered(self, event): + """Callback for object:row-reordered accessibility events.""" + + if super().onRowReordered(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onRowReordered(self, event) + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + if super().onSelectedChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onSelectedChanged(self, event) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if super().onSelectionChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onSelectionChanged(self, event) + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + if super().onShowingChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onShowingChanged(self, event) + + def onTextAttributesChanged(self, event): + """Callback for object:text-attributes-changed accessibility events.""" + + if super().onTextAttributesChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextAttributesChanged(self, event) + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if super().onTextDeleted(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextDeleted(self, event) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if super().onTextInserted(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextInserted(self, event) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + if super().onTextSelectionChanged(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onTextSelectionChanged(self, event) + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + if not self.utilities.canBeActiveWindow(event.source): + return + + if super().onWindowActivated(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onWindowActivated(self, event) + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + if super().onWindowDeactivated(event): + return + + msg = "GECKO: Passing along event to default script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + default.Script.onWindowDeactivated(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script_utilities.py new file mode 100644 index 0000000..826b74b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Gecko/script_utilities.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Commonly-required utility methods needed by -- and potentially + customized by -- application and toolkit scripts. They have + been pulled out from the scripts because certain scripts had + gotten way too large as a result of including these methods.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." \ + "Copyright (c) 2014-2015 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import re +import time + +from cthulhu import debug +from cthulhu import cthulhu_state +from cthulhu.scripts import web +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(web.Utilities): + + def __init__(self, script): + super().__init__(script) + self._lastAutoTextObjectEvent = None + self._lastAutoTextInputEvent = None + self._lastAutoTextEventTime = 0 + + def _attemptBrokenTextRecovery(self, obj, **args): + boundary = args.get('boundary') + + # Gecko fails to implement this boundary type. + if boundary == Atspi.TextBoundaryType.SENTENCE_START: + return True + + if self.isContentEditableWithEmbeddedObjects(obj): + return boundary == Atspi.TextBoundaryType.WORD_START + + return True + + def _treatAsLeafNode(self, obj): + if AXUtilities.is_table_row(obj): + return not AXObject.get_child_count(obj) + + return super()._treatAsLeafNode(obj) + + def containsPoint(self, obj, x, y, coordType, margin=2): + if not super().containsPoint(obj, x, y, coordType, margin): + return False + + if (AXUtilities.is_menu(obj) or AXUtilities.is_tool_tip(obj)) \ + and self.topLevelObject(obj) == AXObject.get_parent(obj): + tokens = ["GECKO:", obj, "is suspected to be off screen object"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + def isLayoutOnly(self, obj): + if super().isLayoutOnly(obj): + return True + + if AXUtilities.is_tool_bar(obj) and AXObject.get_child_count(obj): + return AXUtilities.is_page_tab_list(AXObject.get_child(obj, 0)) + + return False + + def isSameObject(self, obj1, obj2, comparePaths=False, ignoreNames=False, + ignoreDescriptions=True): + if super().isSameObject(obj1, obj2, comparePaths, ignoreNames, ignoreDescriptions): + return True + + roles = self._topLevelRoles() + if not (AXObject.get_role(obj1) in roles and AXObject.get_role(obj2) in roles): + return False + + rv = AXObject.get_name(obj1) == AXObject.get_name(obj2) + tokens = ["GECKO: Treating", obj1, "and", obj2, "as same object:", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def isOnScreen(self, obj, boundingbox=None): + if not super().isOnScreen(obj, boundingbox): + return False + if not AXUtilities.is_unknown(obj): + return True + + if self.topLevelObject(obj) == AXObject.get_parent(obj): + tokens = ["INFO:", obj, "is suspected to be off screen object"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + def getOnScreenObjects(self, root, extents=None): + objects = super().getOnScreenObjects(root, extents) + + # For things like Thunderbird's "Select columns to display" button + if AXUtilities.is_tree_table(root) and AXObject.get_child_count(root): + + def isExtra(x): + return not AXUtilities.is_column_header(x) + + child = AXObject.get_child(root, 0) + objects.extend([x for x in AXObject.iter_children(child, isExtra)]) + + return objects + + def isEditableMessage(self, obj): + """Returns True if this is an editable message.""" + + if not AXUtilities.is_editable(obj): + return False + + document = self.getDocumentForObject(obj) + if AXUtilities.is_editable(document): + tokens = ["GECKO:", obj, "is in an editable document:", document] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + tokens = ["GECKO: Editable", obj, "not in an editable document"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + def isNotRealDocument(self, obj): + name = AXObject.get_name(obj) + if name.startswith("moz-extension"): + return True + + if "self-repair.mozilla.org" in name: + return True + + uri = self.documentFrameURI(obj) + if uri.startswith("moz-extension"): + return True + + if not uri and "pixels" in name: + return True + + return False + + def _objectMightBeBogus(self, obj): + if AXUtilities.is_section(obj) and AXUtilities.is_frame(AXObject.get_parent(obj)): + tokens = ["GECKO:", obj, "is believed to be a bogus object"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def canBeActiveWindow(self, window, clearCache=False): + # We apparently having missing events from Gecko requiring + # we update the cache. This is not performant. :( + return super().canBeActiveWindow(window, True) + + def treatAsEntry(self, obj): + if not obj or self.inDocumentContent(obj): + return super().treatAsEntry(obj) + + # Firefox seems to have turned its accessible location widget into a + # childless editable combobox. + if not AXUtilities.is_combo_box(obj): + return False + + if AXObject.get_child_count(obj): + return False + + if not AXUtilities.is_focused(obj): + return False + + if not AXObject.supports_editable_text(obj): + return False + + tokens = ["GECKO: Treating", obj, "as entry"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def _isQuickFind(self, obj): + if not obj or self.inDocumentContent(obj): + return False + + if obj == self._findContainer: + return True + + if not AXUtilities.is_tool_bar(obj): + return False + + # TODO: This would be far easier if Gecko gave us an object attribute to look for.... + + if len(AXUtilities.find_all_entries(obj)) != 1: + tokens = ["GECKO:", obj, "not believed to be quick-find container (entry count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if len(AXUtilities.find_all_push_buttons(obj)) != 1: + tokens = ["GECKO:", obj, "not believed to be quick-find container (button count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["GECKO:", obj, "believed to be quick-find container (accessibility tree)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._findContainer = obj + return True + + def isFindContainer(self, obj): + if not obj or self.inDocumentContent(obj): + return False + + if obj == self._findContainer: + return True + + if not AXUtilities.is_tool_bar(obj): + return False + + result = self.getFindResultsCount(obj) + if result: + tokens = ["GECKO:", obj, "believed to be find-in-page container (", result, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._findContainer = obj + return True + + # TODO: This would be far easier if Gecko gave us an object attribute to look for.... + + if len(AXUtilities.find_all_entries(obj)) != 1: + tokens = ["GECKO:", obj, "not believed to be find-in-page container (entry count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if len(AXUtilities.find_all_push_buttons(obj)) < 5: + tokens = ["GECKO:", obj, "not believed to be find-in-page container (button count)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + tokens = ["GECKO:", obj, "believed to be find-in-page container (accessibility tree)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._findContainer = obj + return True + + def inFindContainer(self, obj=None): + if not obj: + obj = cthulhu_state.locusOfFocus + + if not obj or self.inDocumentContent(obj): + return False + + if not (AXUtilities.is_entry(obj) or AXUtilities.is_push_button(obj)): + return False + + toolbar = AXObject.find_ancestor(obj, AXUtilities.is_tool_bar) + result = self.isFindContainer(toolbar) + if result: + tokens = ["GECKO:", obj, "believed to be find-in-page widget (toolbar)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self._isQuickFind(toolbar): + tokens = ["GECKO:", obj, "believed to be find-in-page widget (quick find)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def getFindResultsCount(self, root=None): + root = root or self._findContainer + if not root: + return "" + + def isMatch(x): + return len(re.findall(r"\d+", AXObject.get_name(x))) == 2 + + labels = AXUtilities.find_all_labels(root, isMatch) + if len(labels) != 1: + return "" + + label = labels[0] + AXObject.clear_cache(label) + return AXObject.get_name(label) + + def isAutoTextEvent(self, event): + if not super().isAutoTextEvent(event): + return False + + if self.inDocumentContent(event.source): + return True + + if self.treatAsDuplicateEvent(self._lastAutoTextObjectEvent, event) \ + and time.time() - self._lastAutoTextEventTime < 0.5 \ + and cthulhu_state.lastInputEvent.isReleaseFor(self._lastAutoTextInputEvent): + msg = "GECKO: Event believed to be duplicate auto text event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + self._lastAutoTextObjectEvent = event + self._lastAutoTextInputEvent = cthulhu_state.lastInputEvent + self._lastAutoTextEventTime = time.time() + return True + + def localizeTextAttribute(self, key, value): + value = value.replace("-moz-", "") + return super().localizeTextAttribute(key, value) + + def unrelatedLabels(self, root, onlyShowing=True, minimumWords=3): + return super().unrelatedLabels(root, onlyShowing, minimumWords=1) + + def _shouldUseTableCellInterfaceForCoordinates(self): + # https://bugzilla.mozilla.org/show_bug.cgi?id=1794100 + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/__init__.py new file mode 100644 index 0000000..9a70c54 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/__init__.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script +from .speech_generator import SpeechGenerator diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/formatting.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/formatting.py new file mode 100644 index 0000000..d17a42d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/formatting.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom formatting for Java Swing.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc., " \ + "Copyright (c) 2010 Joanmarie Diggs" +__license__ = "LGPL" + +# If we were to adhere to the line-length requirements of 100 characters, +# this file would be even more cumbersome to look at than it already is. +# We shall respect the line-length requirements for all files that are not +# formatting.py. +# ruff: noqa: E501 + +import copy +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.formatting + +formatting = { + 'speech': { + # In Java, tree objects are labels, so we need to look at their + # states in order to tell whether they are expanded or collapsed. + # + Atspi.Role.LABEL: { + 'unfocused': '(displayedText or roleName) + expandableState + numberOfChildren', + 'focused': 'expandableState + numberOfChildren', + 'basicWhereAmI': '(displayedText or roleName) + expandableState + numberOfChildren + nodeLevel', + }, + }, + 'braille': { + Atspi.Role.LABEL: { + 'unfocused': '[Component(obj, asString(displayedText + expandableState))]' + }, + } +} + +class Formatting(cthulhu.formatting.Formatting): + def __init__(self, script): + cthulhu.formatting.Formatting.__init__(self, script) + self.update(copy.deepcopy(formatting)) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script.py new file mode 100644 index 0000000..49fca20 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc., " \ + "Copyright (c) 2010 Joanmarie Diggs" +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.scripts.default as default +import cthulhu.input_event as input_event +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.ax_selection import AXSelection +from cthulhu.ax_utilities import AXUtilities + +from .script_utilities import Utilities +from .speech_generator import SpeechGenerator +from .formatting import Formatting + +######################################################################## +# # +# The Java script class. # +# # +######################################################################## + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for Java applications. + + Arguments: + - app: the application to create a script for. + """ + default.Script.__init__(self, app) + + # Some objects which issue descendant changed events lack + # STATE_MANAGES_DESCENDANTS. As a result, onSelectionChanged + # doesn't ignore these objects. That in turn causes Cthulhu to + # double-speak some items and/or set the locusOfFocus to a + # parent it shouldn't. See bgo#616582. [[[TODO - JD: remove + # this hack if and when we get a fix for that bug]]] + # + self.lastDescendantChangedSource = None + + def getSpeechGenerator(self): + """Returns the speech generator for this script.""" + return SpeechGenerator(self) + + def getFormatting(self): + """Returns the formatting strings for this script.""" + return Formatting(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + return Utilities(self) + + def onCaretMoved(self, event): + # Java's SpinButtons are the most caret movement happy thing + # I've seen to date. If you Up or Down on the keyboard to + # change the value, they typically emit three caret movement + # events, first to the beginning, then to the end, and then + # back to the beginning. It's a very excitable little widget. + # Luckily, it only issues one value changed event. So, we'll + # ignore caret movement events caused by value changes and + # just process the single value changed event. + # + isSpinBox = self.utilities.hasMatchingHierarchy( + event.source, [Atspi.Role.TEXT, + Atspi.Role.PANEL, + Atspi.Role.SPIN_BUTTON]) + if isSpinBox: + eventStr, mods = self.utilities.lastKeyAndModifiers() + if eventStr in ["Up", "Down"] or isinstance( + cthulhu_state.lastInputEvent, input_event.MouseButtonEvent): + return + + default.Script.onCaretMoved(self, event) + + def onSelectionChanged(self, event): + """Called when an object's selection changes. + + Arguments: + - event: the Event + """ + + # Avoid doing this with objects that manage their descendants + # because they'll issue a descendant changed event. (Note: This + # equality check is intentional; utilities.isSameObject() is + # especially thorough with trees and tables, which is not + # performant. + # + if event.source == self.lastDescendantChangedSource: + return + + # We treat selected children as the locus of focus. When the + # selection changes in a list we want to update the locus of + # focus. If there is no selection, we default the locus of + # focus to the containing object. + # + if (AXUtilities.is_list(event.source) \ + or AXUtilities.is_page_tab_list(event.source) \ + or AXUtilities.is_tree(event.source)) \ + and AXUtilities.is_focused(event.source): + newFocus = AXSelection.get_selected_child(event.source, 0) or event.source + cthulhu.setLocusOfFocus(event, newFocus) + else: + default.Script.onSelectionChanged(self, event) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + return + + # Accessibility support for menus in Java is badly broken: Missing + # events, missing states, bogus events from other objects, etc. + # Therefore if we get an event, however broken, for menus or their + # their items that suggests they are selected, we'll just cross our + # fingers and hope that's true. + if AXUtilities.is_menu_related(event.source) \ + or AXUtilities.is_menu_related(AXObject.get_parent(event.source)): + cthulhu.setLocusOfFocus(event, event.source) + return + + if AXUtilities.is_root_pane(event.source) \ + and AXUtilities.is_menu_related(cthulhu_state.locusOfFocus): + return + + default.Script.onFocusedChanged(self, event) + + def onValueChanged(self, event): + """Called whenever an object's value changes. + + Arguments: + - event: the Event + """ + + # We'll ignore value changed events for Java's toggle buttons since + # they also send a redundant object:state-changed:checked event. + if AXUtilities.is_toggle_button(event.source) \ + or AXUtilities.is_radio_button(event.source) \ + or AXUtilities.is_check_box(event.source): + return + + # Java's SpinButtons are the most caret movement happy thing + # I've seen to date. If you Up or Down on the keyboard to + # change the value, they typically emit three caret movement + # events, first to the beginning, then to the end, and then + # back to the beginning. It's a very excitable little widget. + # Luckily, it only issues one value changed event. So, we'll + # ignore caret movement events caused by value changes and + # just process the single value changed event. + # + if AXUtilities.is_spin_button(event.source): + parent = AXObject.get_parent(cthulhu_state.locusOfFocus) + grandparent = AXObject.get_parent(parent) + if grandparent == event.source: + self._presentTextAtNewCaretPosition(event, cthulhu_state.locusOfFocus) + return + + default.Script.onValueChanged(self, event) + + def skipObjectEvent(self, event): + + # Accessibility support for menus in Java is badly broken. One problem + # is bogus focus claims following menu-related focus claims. Therefore + # in this particular toolkit, we mustn't skip events for menus. + if AXUtilities.is_menu_related(event.source): + return False + + return default.Script.skipObjectEvent(self, event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script_utilities.py new file mode 100644 index 0000000..0bdd0bb --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/script_utilities.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Commonly-required utility methods needed by -- and potentially + customized by -- application and toolkit scripts. They have + been pulled out from the scripts because certain scripts had + gotten way too large as a result of including these methods.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." +__license__ = "LGPL" + +import cthulhu.script_utilities as script_utilities +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +############################################################################# +# # +# Utilities # +# # +############################################################################# + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + """Creates an instance of the Utilities class. + + Arguments: + - script: the script with which this instance is associated. + """ + + script_utilities.Utilities.__init__(self, script) + + ######################################################################### + # # + # Utilities for finding, identifying, and comparing accessibles # + # # + ######################################################################### + + def isSameObject(self, obj1, obj2, comparePaths=False, ignoreNames=False, + ignoreDescriptions=True): + """Compares two objects to determine if they are functionally + the same object. This is needed because some applications and + toolkits kill and replace accessibles.""" + + if obj1 == obj2: + return True + if obj1 is None or obj2 is None: + return False + if not ignoreNames and AXObject.get_name(obj1) != AXObject.get_name(obj2): + return False + if AXObject.get_child_count(obj1) != AXObject.get_child_count(obj2): + return False + + # This is to handle labels in trees. In some cases the default + # script's method gives us false positives; other times false + # negatives. + # + if AXUtilities.is_label(obj1) and AXUtilities.is_label(obj2): + try: + ext1 = obj1.queryComponent().getExtents(0) + ext2 = obj2.queryComponent().getExtents(0) + except Exception: + pass + else: + if ext1.x == ext2.x and ext1.y == ext2.y \ + and ext1.width == ext2.width and ext1.height == ext2.height: + return True + + # In java applications, TRANSIENT state is missing for tree items + # (fix for bug #352250) + # + parent1 = obj1 + parent2 = obj2 + while AXUtilities.is_label(parent1) and AXUtilities.is_label(parent2): + if AXObject.get_index_in_parent(parent1) != AXObject.get_index_in_parent(parent2): + return False + parent1 = AXObject.get_parent(parent1) + parent2 = AXObject.get_parent(parent2) + if parent1 and parent2 and parent1 == parent2: + return True + + return script_utilities.Utilities.isSameObject( + self, obj1, obj2, comparePaths, ignoreNames, ignoreDescriptions) + + def nodeLevel(self, obj): + """Determines the node level of this object if it is in a tree + relation, with 0 being the top level node. If this object is + not in a tree relation, then -1 will be returned. + + Arguments: + -obj: the Accessible object + """ + + newObj = obj + if newObj and self.isZombie(newObj): + newObj = self.findReplicant(self._script.lastDescendantChangedSource, obj) + + if not newObj: + return script_utilities.Utilities.nodeLevel(self, obj) + + count = 0 + while newObj: + if AXUtilities.is_expandable(newObj) or AXUtilities.is_collapsed(newObj): + if AXUtilities.is_visible(newObj): + count += 1 + newObj = AXObject.get_parent(newObj) + else: + break + + return count - 1 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/speech_generator.py new file mode 100644 index 0000000..f3ca517 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/J2SE-access-bridge/speech_generator.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc., " \ + "Copyright (c) 2010 Joanmarie Diggs" +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.messages as messages +import cthulhu.settings as settings +import cthulhu.settings_manager as settings_manager +import cthulhu.speech_generator as speech_generator +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# Speech Generator # +# # +######################################################################## + +class SpeechGenerator(speech_generator.SpeechGenerator): + + def __init__(self, script): + speech_generator.SpeechGenerator.__init__(self, script) + + def _generateAncestors(self, obj, **args): + """The Swing toolkit has labelled panels that do not implement the + AccessibleText interface, but displayedText returns a meaningful + string that needs to be used if displayedLabel returns None. + """ + args['requireText'] = False + result = speech_generator.SpeechGenerator._generateAncestors( + self, obj, **args) + del args['requireText'] + return result + + def _generateNewAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object. This is typically used to present the context for + an object (e.g., the names of the window, the panels, etc., + that the object is contained in). If the 'priorObj' attribute + of the args dictionary is set, only the differences in + ancestry between the 'priorObj' and the current obj will be + computed. Otherwise, no ancestry will be computed. The + 'priorObj' is typically set by Cthulhu to be the previous object + with focus. + """ + result = [] + if args.get('role', AXObject.get_role(obj)) == Atspi.Role.MENU: + # We're way too chatty here -- at least with the Swing2 + # demo. Users entering a menu want to know they've gone + # into a menu; not a huge ancestry. + # + return result + result.extend(speech_generator.SpeechGenerator.\ + _generateNewAncestors(self, obj, **args)) + return result + + def _generateNumberOfChildren(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represents the number of children the + object has.""" + + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or _settingsManager.getSetting('speechVerbosityLevel') == settings.VERBOSITY_LEVEL_BRIEF: + return [] + + result = [] + childCount = AXObject.get_child_count(obj) + if childCount and AXUtilities.is_label(obj) \ + and AXUtilities.is_expanded(obj): + result.append(messages.itemCount(childCount)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + else: + result.extend(speech_generator.SpeechGenerator.\ + _generateNumberOfChildren(self, obj, **args)) + + return result + + def _generatePositionInList(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the relative position of an + object in a list. + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + listObj = None + if AXUtilities.is_combo_box(obj): + allLists = AXUtilities.find_all_lists(obj) + if len(allLists) == 1: + listObj = allLists[0] + + if listObj is None: + return speech_generator.SpeechGenerator._generatePositionInList( + self, obj, **args) + + result = [] + name = self._generateName(obj) + position = -1 + index = total = 0 + + for child in AXObject.iter_children(listObj): + nextName = self._generateName(child) + if not nextName or nextName[0] in ["", "Empty", "separator"] \ + or not AXUtilities.is_visible(child): + continue + + index += 1 + total += 1 + + if nextName == name: + position = index + + if (_settingsManager.getSetting('enablePositionSpeaking') \ + or args.get('forceList', False)) \ + and position >= 0: + result.append(self._script.formatting.getString( + mode='speech', stringType='groupindex') \ + % {"index" : position, "total" : total}) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + def generateSpeech(self, obj, **args): + result = [] + if AXUtilities.is_check_box(obj) and AXUtilities.is_menu(AXObject.get_parent(obj)): + oldRole = self._overrideRole(Atspi.Role.CHECK_MENU_ITEM, args) + result.extend(speech_generator.SpeechGenerator.\ + generateSpeech(self, obj, **args)) + self._restoreRole(oldRole, args) + + if args.get('formatType', 'unfocused') == 'basicWhereAmI' and AXUtilities.is_text(obj): + spinbox = AXObject.find_ancestor(obj, AXUtilities.is_spin_button) + if spinbox is not None: + obj = spinbox + result.extend(speech_generator.SpeechGenerator.generateSpeech(self, obj, **args)) + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script.py new file mode 100644 index 0000000..490fd25 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013-2019 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.cthulhu as cthulhu +import cthulhu.scripts.default as default +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .script_utilities import Utilities + +class Script(default.Script): + + def __init__(self, app): + super().__init__(app) + + def getUtilities(self): + return Utilities(self) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if AXUtilities.is_accelerator_label(event.source): + msg = "QT: Ignoring event due to role." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().onCaretMoved(event) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + return + + if AXUtilities.is_accelerator_label(event.source): + msg = "QT: Ignoring event due to role." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + frame = self.utilities.topLevelObject(event.source) + if not frame: + msg = "QT: Ignoring event because we couldn't find an ancestor window." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + isActive = AXUtilities.is_active(frame) + if not isActive: + tokens = ["QT: Event came from inactive top-level object", frame] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + AXObject.clear_cache(frame) + isActive = AXUtilities.is_active(frame) + tokens = ["QT: Cleared cache of", frame, ". Frame is now active:", isActive] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if AXUtilities.is_focused(event.source): + super().onFocusedChanged(event) + return + + msg = "QT: WARNING - source lacks focused state. Setting focus anyway." + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script_utilities.py new file mode 100644 index 0000000..37c0569 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/Qt/script_utilities.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2023 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities + +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + super().__init__(script) + + def _isTopLevelObject(self, obj): + # This is needed because Qt apps might insert some junk (e.g. a filler) in + # between the window/frame/dialog and the application. + return AXUtilities.is_application(AXObject.get_parent(obj)) + + def topLevelObject(self, obj, useFallbackSearch=False): + # The fallback search is needed because sometimes we can ascend the accessibility + # tree all the way to the top; other times, we cannot get the parent, but can still + # get the children. The fallback search handles the latter scenario. + result = super().topLevelObject(obj, useFallbackSearch=True) + if result is not None and AXObject.get_role(result) not in self._topLevelRoles(): + tokens = ["QT: Top level object", result, "lacks expected role."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return result + + def frameAndDialog(self, obj): + """Returns the frame and (possibly) the dialog containing obj.""" + + frame, dialog = super().frameAndDialog(obj) + if frame or dialog: + return frame, dialog + + tokens = ["QT: Could not find frame or dialog for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + topLevel = self.topLevelObject(obj, True) + + tokens = ["QT: Returning", topLevel, "as frame for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return topLevel, None + + def hasMeaningfulToggleAction(self, obj): + """Returns True if obj has a meaningful toggle action.""" + + # https://bugreports.qt.io/browse/QTBUG-116204 + if AXUtilities.is_table_cell_or_header(obj): + tokens = ["QT: Ignoring toggle action on", obj, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return super().hasMeaningfulToggleAction(obj) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/VCL.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/VCL.py new file mode 100644 index 0000000..ec98218 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/VCL.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Custom script for VCL toolkit (OpenOffice) applications""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +import cthulhu.scripts.default + +class Script(cthulhu.default.Script): + pass diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/__init__.py new file mode 100644 index 0000000..923e857 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/__init__.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script +from .speech_generator import SpeechGenerator +from .braille_generator import BrailleGenerator +from .script_utilities import Utilities diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/braille_generator.py new file mode 100644 index 0000000..d8af82c --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/braille_generator.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs" \ + "Copyright (c) 2011-2012 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.object_properties as object_properties +import cthulhu.braille_generator as braille_generator +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +######################################################################## +# # +# Custom BrailleGenerator # +# # +######################################################################## + +class BrailleGenerator(braille_generator.BrailleGenerator): + """Provides a braille generator specific to WebKitGtk.""" + + def __init__(self, script): + braille_generator.BrailleGenerator.__init__(self, script) + + def __generateHeadingRole(self, obj): + result = [] + level = self._script.utilities.headingLevel(obj) + result.append(object_properties.ROLE_HEADING_LEVEL_BRAILLE % level) + + return result + + def _generateRoleName(self, obj, **args): + """Prevents some roles from being displayed.""" + + doNotDisplay = [Atspi.Role.FORM, + Atspi.Role.SECTION, + Atspi.Role.UNKNOWN] + if not AXUtilities.is_focusable(obj): + doNotDisplay.extend([Atspi.Role.LIST, + Atspi.Role.LIST_ITEM, + Atspi.Role.PANEL]) + + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.HEADING: + result.extend(self.__generateHeadingRole(obj)) + elif role not in doNotDisplay: + result.extend(braille_generator.BrailleGenerator._generateRoleName( + self, obj, **args)) + parent = AXObject.get_parent(obj) + if AXObject.get_role(parent) == Atspi.Role.HEADING: + result.extend(self.__generateHeadingRole(parent)) + + return result + + def _generateAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object. This is typically used to present the context for + an object (e.g., the names of the window, the panels, etc., + that the object is contained in). If the 'priorObj' attribute + of the args dictionary is set, only the differences in + ancestry between the 'priorObj' and the current obj will be + computed. The 'priorObj' is typically set by Cthulhu to be the + previous object with focus. + """ + + if self._script.utilities.isWebKitGtk(obj): + return [] + + return braille_generator.BrailleGenerator._generateAncestors( + self, obj, **args) + + def _generateEol(self, obj, **args): + if self._script.utilities.isWebKitGtk(obj) \ + and AXObject.get_role(obj) == Atspi.Role.PARAGRAPH \ + and not AXUtilities.is_editable(obj): + return [] + + return braille_generator.BrailleGenerator._generateEol( + self, obj, **args) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script.py new file mode 100644 index 0000000..7e017e5 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script.py @@ -0,0 +1,662 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (C) 2010-2011 The Cthulhu Team" \ + "Copyright (C) 2011-2012 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.scripts.default as default +import cthulhu.cmdnames as cmdnames +import cthulhu.debug as debug +import cthulhu.guilabels as guilabels +import cthulhu.input_event as input_event +import cthulhu.messages as messages +import cthulhu.cthulhu as cthulhu +import cthulhu.settings as settings +import cthulhu.settings_manager as settings_manager +import cthulhu.speechserver as speechserver +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.speech as speech +import cthulhu.structural_navigation as structural_navigation +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .braille_generator import BrailleGenerator +from .speech_generator import SpeechGenerator +from .script_utilities import Utilities + +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# The WebKitGtk script class. # +# # +######################################################################## + +class Script(default.Script): + + def __init__(self, app): + """Creates a new script for WebKitGtk applications. + + Arguments: + - app: the application to create a script for. + """ + + super().__init__(app) + self._loadingDocumentContent = False + self._lastCaretContext = None, -1 + self.sayAllOnLoadCheckButton = None + + if _settingsManager.getSetting('sayAllOnLoad') is None: + _settingsManager.setSetting('sayAllOnLoad', True) + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for this script that can be + called by the key and braille bindings.""" + + default.Script.setupInputEventHandlers(self) + self.inputEventHandlers.update( + self.structuralNavigation.inputEventHandlers) + + self.inputEventHandlers["sayAllHandler"] = \ + input_event.InputEventHandler( + Script.sayAll, + cmdnames.SAY_ALL) + + self.inputEventHandlers["panBrailleLeftHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleLeft, + cmdnames.PAN_BRAILLE_LEFT, + False) # Do not enable learn mode for this action + + self.inputEventHandlers["panBrailleRightHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleRight, + cmdnames.PAN_BRAILLE_RIGHT, + False) # Do not enable learn mode for this action + + def getToolkitKeyBindings(self): + """Returns the toolkit-specific keybindings for this script.""" + + return self.structuralNavigation.keyBindings + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing the application unique configuration + GUI items for the current application.""" + + from gi.repository import Gtk + + grid = Gtk.Grid() + grid.set_border_width(12) + + label = guilabels.READ_PAGE_UPON_LOAD + self.sayAllOnLoadCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self.sayAllOnLoadCheckButton.set_active( + _settingsManager.getSetting('sayAllOnLoad')) + grid.attach(self.sayAllOnLoadCheckButton, 0, 0, 1, 1) + + grid.show_all() + + return grid + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return {'sayAllOnLoad': self.sayAllOnLoadCheckButton.get_active()} + + def getBrailleGenerator(self): + """Returns the braille generator for this script.""" + + return BrailleGenerator(self) + + def getSpeechGenerator(self): + """Returns the speech generator for this script.""" + + return SpeechGenerator(self) + + def getEnabledStructuralNavigationTypes(self): + """Returns a list of the structural navigation object types + enabled in this script.""" + + return [structural_navigation.StructuralNavigation.BLOCKQUOTE, + structural_navigation.StructuralNavigation.BUTTON, + structural_navigation.StructuralNavigation.CHECK_BOX, + structural_navigation.StructuralNavigation.CHUNK, + structural_navigation.StructuralNavigation.CLICKABLE, + structural_navigation.StructuralNavigation.COMBO_BOX, + structural_navigation.StructuralNavigation.CONTAINER, + structural_navigation.StructuralNavigation.ENTRY, + structural_navigation.StructuralNavigation.FORM_FIELD, + structural_navigation.StructuralNavigation.HEADING, + structural_navigation.StructuralNavigation.IFRAME, + structural_navigation.StructuralNavigation.IMAGE, + structural_navigation.StructuralNavigation.LANDMARK, + structural_navigation.StructuralNavigation.LINK, + structural_navigation.StructuralNavigation.LIST, + structural_navigation.StructuralNavigation.LIST_ITEM, + structural_navigation.StructuralNavigation.LIVE_REGION, + structural_navigation.StructuralNavigation.PARAGRAPH, + structural_navigation.StructuralNavigation.RADIO_BUTTON, + structural_navigation.StructuralNavigation.SEPARATOR, + structural_navigation.StructuralNavigation.TABLE, + structural_navigation.StructuralNavigation.TABLE_CELL, + structural_navigation.StructuralNavigation.UNVISITED_LINK, + structural_navigation.StructuralNavigation.VISITED_LINK] + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + if self._inSayAll: + return + + if not self.utilities.isWebKitGtk(event.source): + super().onCaretMoved(event) + return + + lastKey, mods = self.utilities.lastKeyAndModifiers() + if lastKey in ['Tab', 'ISO_Left_Tab']: + return + + if lastKey == 'Down' \ + and cthulhu_state.locusOfFocus == AXObject.get_parent(event.source) \ + and AXObject.get_index_in_parent(event.source) == 0 \ + and AXUtilities.is_link(cthulhu_state.locusOfFocus): + self.updateBraille(event.source) + return + + self.utilities.setCaretContext(event.source, event.detail1) + super().onCaretMoved(event) + + def onDocumentReload(self, event): + """Callback for document:reload accessibility events.""" + + if self.utilities.treatAsBrowser(event.source): + self._loadingDocumentContent = True + + def onDocumentLoadComplete(self, event): + """Callback for document:load-complete accessibility events.""" + + if not self.utilities.treatAsBrowser(event.source): + return + + self._loadingDocumentContent = False + + # TODO: We need to see what happens in Epiphany on pages where focus + # is grabbed rather than set the caret at the start. But for simple + # content in both Yelp and Epiphany this is alright for now. + obj, offset = self.utilities.setCaretAtStart(event.source) + self.utilities.setCaretContext(obj, offset) + + self.updateBraille(obj) + if _settingsManager.getSetting('sayAllOnLoad') \ + and _settingsManager.getSetting('enableSpeech'): + self.sayAll(None) + + def onDocumentLoadStopped(self, event): + """Callback for document:load-stopped accessibility events.""" + + if self.utilities.treatAsBrowser(event.source): + self._loadingDocumentContent = False + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if self._inSayAll or not event.detail1: + return + + if not self.utilities.isWebKitGtk(event.source): + super().onFocusedChanged(event) + return + + contextObj, offset = self.utilities.getCaretContext() + if event.source == contextObj: + return + + obj = event.source + role = AXObject.get_role(obj) + textRoles = [Atspi.Role.HEADING, + Atspi.Role.PANEL, + Atspi.Role.PARAGRAPH, + Atspi.Role.SECTION, + Atspi.Role.TABLE_CELL] + if role in textRoles \ + or (role == Atspi.Role.LIST_ITEM and AXObject.get_child_count(obj)): + return + + super().onFocusedChanged(event) + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + + if not self.utilities.treatAsBrowser(event.source): + return + + if event.detail1: + self.presentMessage(messages.PAGE_LOADING_START) + return + + name = AXObject.get_name(event.source) + if name: + self.presentMessage(messages.PAGE_LOADING_END_NAMED % name) + else: + self.presentMessage(messages.PAGE_LOADING_END) + + def sayCharacter(self, obj): + """Speak the character at the caret. + + Arguments: + - obj: an Accessible object that implements the AccessibleText interface + """ + + if AXUtilities.is_entry(obj): + default.Script.sayCharacter(self, obj) + return + + boundary = Atspi.TextBoundaryType.CHAR + objects = self.utilities.getObjectsFromEOCs(obj, boundary=boundary) + for (obj, start, end, string) in objects: + if string: + self.speakCharacter(string) + else: + speech.speak(self.speechGenerator.generateSpeech(obj)) + + self.pointOfReference["lastTextUnitSpoken"] = "char" + + def sayWord(self, obj): + """Speaks the word at the caret. + + Arguments: + - obj: an Accessible object that implements the AccessibleText interface + """ + + if AXUtilities.is_entry(obj): + default.Script.sayWord(self, obj) + return + + boundary = Atspi.TextBoundaryType.WORD_START + objects = self.utilities.getObjectsFromEOCs(obj, boundary=boundary) + for (obj, start, end, string) in objects: + self.sayPhrase(obj, start, end) + + self.pointOfReference["lastTextUnitSpoken"] = "word" + + def sayLine(self, obj): + """Speaks the line at the caret. + + Arguments: + - obj: an Accessible object that implements the AccessibleText interface + """ + + if AXUtilities.is_entry(obj): + default.Script.sayLine(self, obj) + return + + boundary = Atspi.TextBoundaryType.LINE_START + objects = self.utilities.getObjectsFromEOCs(obj, boundary=boundary) + for (obj, start, end, string) in objects: + self.sayPhrase(obj, start, end) + + # TODO: Move these next items into the speech generator. + if AXUtilities.is_panel(obj) and AXObject.get_index_in_parent(obj) == 0: + obj = AXObject.get_parent(obj) + + rolesToSpeak = [Atspi.Role.HEADING, Atspi.Role.LINK] + if AXObject.get_role(obj) in rolesToSpeak: + speech.speak(self.speechGenerator.getRoleName(obj)) + + self.pointOfReference["lastTextUnitSpoken"] = "line" + + def sayPhrase(self, obj, startOffset, endOffset): + """Speaks the text of an Accessible object between the given offsets. + + Arguments: + - obj: an Accessible object that implements the AccessibleText interface + - startOffset: the start text offset. + - endOffset: the end text offset. + """ + + if AXUtilities.is_entry(obj): + default.Script.sayPhrase(self, obj, startOffset, endOffset) + return + + phrase = self.utilities.substring(obj, startOffset, endOffset) + if len(phrase) and phrase != "\n": + voice = self.speechGenerator.voice(obj=obj, string=phrase) + phrase = self.utilities.adjustForRepeats(phrase) + links = [x for x in AXObject.iter_children(obj, AXUtilities.is_link)] + if links: + phrase = self.utilities.adjustForLinks(obj, phrase, startOffset) + speech.speak(phrase, voice) + else: + # Speak blank line if appropriate. + # + self.sayCharacter(obj) + + self.pointOfReference["lastTextUnitSpoken"] = "phrase" + + def skipObjectEvent(self, event): + """Gives us, and scripts, the ability to decide an event isn't + worth taking the time to process under the current circumstances. + + Arguments: + - event: the Event + + Returns True if we shouldn't bother processing this object event. + """ + + if event.type.startswith('object:state-changed:focused') and event.detail1 \ + and AXUtilities.is_link(event.source): + return False + + return default.Script.skipObjectEvent(self, event) + + def useStructuralNavigationModel(self, debugOutput=True): + """Returns True if we should do our own structural navigation. + This should return False if we're in a form field, or not in + document content. + """ + + doNotHandleRoles = [Atspi.Role.ENTRY, + Atspi.Role.TEXT, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.LIST, + Atspi.Role.LIST_ITEM, + Atspi.Role.MENU_ITEM] + + if not self.structuralNavigation.enabled: + return False + + if not self.utilities.isWebKitGtk(cthulhu_state.locusOfFocus): + return False + + if AXUtilities.is_editable(cthulhu_state.locusOfFocus): + return False + + role = AXObject.get_role(cthulhu_state.locusOfFocus) + if role in doNotHandleRoles: + if role == Atspi.Role.LIST_ITEM: + return not AXUtilities.is_selectable(cthulhu_state.locusOfFocus) + + if AXUtilities.is_focused(cthulhu_state.locusOfFocus): + return False + + return True + + def panBrailleLeft(self, inputEvent=None, panAmount=0): + """In document content, we want to use the panning keys to browse the + entire document. + """ + + if self.flatReviewPresenter.is_active() \ + or not self.isBrailleBeginningShowing() \ + or not self.utilities.isWebKitGtk(cthulhu_state.locusOfFocus): + return default.Script.panBrailleLeft(self, inputEvent, panAmount) + + obj = self.utilities.findPreviousObject(cthulhu_state.locusOfFocus) + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + self.updateBraille(obj) + + # Hack: When panning to the left in a document, we want to start at + # the right/bottom of each new object. For now, we'll pan there. + # When time permits, we'll give our braille code some smarts. + while self.panBrailleInDirection(panToLeft=False): + pass + self.refreshBraille(False) + + return True + + def panBrailleRight(self, inputEvent=None, panAmount=0): + """In document content, we want to use the panning keys to browse the + entire document. + """ + + if self.flatReviewPresenter.is_active() \ + or not self.isBrailleEndShowing() \ + or not self.utilities.isWebKitGtk(cthulhu_state.locusOfFocus): + return default.Script.panBrailleRight(self, inputEvent, panAmount) + + obj = self.utilities.findNextObject(cthulhu_state.locusOfFocus) + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + self.updateBraille(obj) + + # Hack: When panning to the right in a document, we want to start at + # the left/top of each new object. For now, we'll pan there. When time + # permits, we'll give our braille code some smarts. + while self.panBrailleInDirection(panToLeft=True): + pass + self.refreshBraille(False) + + return True + + def sayAll(self, inputEvent, obj=None, offset=None): + """Speaks the contents of the document beginning with the present + location. Overridden in this script because the sayAll could have + been started on an object without text (such as an image). + """ + + obj = obj or cthulhu_state.locusOfFocus + if not self.utilities.isWebKitGtk(obj): + return default.Script.sayAll(self, inputEvent, obj, offset) + + speech.sayAll(self.textLines(obj, offset), + self.__sayAllProgressCallback) + + return True + + def getTextSegments(self, obj, boundary, offset=0): + segments = [] + text = obj.queryText() + length = text.characterCount + string, start, end = text.getTextAtOffset(offset, boundary) + while string and offset < length: + string = self.utilities.adjustForRepeats(string) + voice = self.speechGenerator.getVoiceForString(obj, string) + string = self.utilities.adjustForLinks(obj, string, start) + # Incrementing the offset should cause us to eventually reach + # the end of the text as indicated by a 0-length string and + # start and end offsets of 0. Sometimes WebKitGtk returns the + # final text segment instead. + if segments and [string, start, end, voice] == segments[-1]: + break + + segments.append([string, start, end, voice]) + offset = end + 1 + string, start, end = text.getTextAtOffset(offset, boundary) + return segments + + def textLines(self, obj, offset=None): + """Creates a generator that can be used to iterate over each line + of a text object, starting at the caret offset. + + Arguments: + - obj: an Accessible that has a text specialization + + Returns an iterator that produces elements of the form: + [SayAllContext, acss], where SayAllContext has the text to be + spoken and acss is an ACSS instance for speaking the text. + """ + + self._sayAllIsInterrupted = False + self._inSayAll = False + if not obj: + return + + if AXObject.get_role(obj) == Atspi.Role.LINK: + obj = AXObject.get_parent(obj) + + document = self.utilities.getDocumentForObject(obj) + if not document or AXUtilities.is_busy(document): + return + + allTextObjs = self.utilities.findAllDescendants( + document, lambda x: AXObject.supports_text(x)) + allTextObjs = allTextObjs[allTextObjs.index(obj):len(allTextObjs)] + textObjs = [x for x in allTextObjs if AXObject.get_parent(x) not in allTextObjs] + if not textObjs: + return + + boundary = Atspi.TextBoundaryType.LINE_START + sayAllStyle = _settingsManager.getSetting('sayAllStyle') + if sayAllStyle == settings.SAYALL_STYLE_SENTENCE: + boundary = Atspi.TextBoundaryType.SENTENCE_START + + voices = _settingsManager.getSetting('voices') + systemVoice = voices.get(settings.SYSTEM_VOICE) + + self._inSayAll = True + offset = textObjs[0].queryText().caretOffset + for textObj in textObjs: + textSegments = self.getTextSegments(textObj, boundary, offset) + roleName = self.speechGenerator.getRoleName(textObj) + if roleName: + textSegments.append([roleName, 0, -1, systemVoice]) + + for (string, start, end, voice) in textSegments: + context = speechserver.SayAllContext(textObj, string, start, end) + self._sayAllContexts.append(context) + self.eventSynthesizer.scroll_into_view(obj, start, end) + yield [context, voice] + + offset = 0 + + self._inSayAll = False + self._sayAllContexts = [] + + def __sayAllProgressCallback(self, context, progressType): + if progressType == speechserver.SayAllContext.PROGRESS: + cthulhu.emitRegionChanged( + context.obj, context.currentOffset, context.currentEndOffset, cthulhu.SAY_ALL) + return + + obj = context.obj + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + + offset = context.currentOffset + text = obj.queryText() + + if progressType == speechserver.SayAllContext.INTERRUPTED: + self._sayAllIsInterrupted = True + if isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + lastKey = cthulhu_state.lastInputEvent.event_string + if lastKey == "Down" and self._fastForwardSayAll(context): + return + elif lastKey == "Up" and self._rewindSayAll(context): + return + + self._inSayAll = False + self._sayAllContexts = [] + if not self._lastCommandWasStructNav: + text.setCaretOffset(offset) + cthulhu.emitRegionChanged(obj, offset) + return + + # SayAllContext.COMPLETED doesn't necessarily mean done with SayAll; + # just done with the current object. If we're still in SayAll, we do + # not want to set the caret (and hence set focus) in a link we just + # passed by. + try: + hypertext = obj.queryHypertext() + except NotImplementedError: + pass + else: + linkCount = hypertext.getNLinks() + links = [hypertext.getLink(x) for x in range(linkCount)] + if [link for link in links if link.startIndex <= offset <= link.endIndex]: + return + + cthulhu.emitRegionChanged(obj, offset, mode=cthulhu.SAY_ALL) + text.setCaretOffset(offset) + + def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None): + """To-be-removed. Returns the string, caretOffset, startOffset.""" + + textLine = super().getTextLineAtCaret(obj, offset, startOffset, endOffset) + string = textLine[0] + if string and string.find(self.EMBEDDED_OBJECT_CHARACTER) == -1 \ + and AXUtilities.is_focused(obj): + return textLine + + textLine[0] = self.utilities.displayedText(obj) + try: + text = obj.queryText() + except Exception: + pass + else: + textLine[1] = min(textLine[1], text.characterCount) + + return textLine + + def updateBraille(self, obj, **args): + """Updates the braille display to show the given object. + + Arguments: + - obj: the Accessible + """ + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: update disabled", True) + return + + if not obj: + return + + if not self.utilities.isWebKitGtk(obj) \ + or (not self.utilities.isInlineContainer(obj) \ + and not self.utilities.isTextListItem(obj)): + default.Script.updateBraille(self, obj, **args) + return + + brailleLine = self.getNewBrailleLine(clearBraille=True, addLine=True) + for child in AXObject.iter_children(obj): + if not self.utilities.onSameLine(child, AXObject.get_child(obj, 0)): + break + [regions, fRegion] = self.brailleGenerator.generateBraille(child) + self.addBrailleRegionsToLine(regions, brailleLine) + + if not brailleLine.regions: + [regions, fRegion] = self.brailleGenerator.generateBraille( + obj, role=Atspi.Role.PARAGRAPH) + self.addBrailleRegionsToLine(regions, brailleLine) + self.setBrailleFocus(fRegion) + + extraRegion = args.get('extraRegion') + if extraRegion: + self.addBrailleRegionToLine(extraRegion, brailleLine) + + self.refreshBraille() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script_utilities.py new file mode 100644 index 0000000..4020c1f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/script_utilities.py @@ -0,0 +1,289 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." \ + "Copyright (c) 2011-2012 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +import re + +import cthulhu.script_utilities as script_utilities +import cthulhu.keybindings as keybindings +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +############################################################################# +# # +# Utilities # +# # +############################################################################# + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + """Creates an instance of the Utilities class. + + Arguments: + - script: the script with which this instance is associated. + """ + super().__init__(script) + + def isWebKitGtk(self, obj): + """Returns True if this object is a WebKitGtk object.""" + + if not obj: + return False + + attrs = self.objectAttributes(obj) + return attrs.get('toolkit', '') in ['WebKitGtk', 'WebKitGTK'] + + def getCaretContext(self): + # TODO - JD: This is private, but it's only here temporarily until we + # have the shared web content support. + obj, offset = self._script._lastCaretContext + if not obj and self.isWebKitGtk(cthulhu_state.locusOfFocus): + obj, offset = super().getCaretContext() + + return obj, offset + + def setCaretContext(self, obj, offset): + # TODO - JD: This is private, but it's only here temporarily until we + # have the shared web content support. + self._script._lastCaretContext = obj, offset + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + + def setCaretPosition(self, obj, offset): + self.setCaretContext(obj, offset) + self.setCaretOffset(obj, offset) + + def isReadOnlyTextArea(self, obj): + """Returns True if obj is a text entry area that is read only.""" + + if not AXUtilities.is_entry(obj): + return False + + if AXUtilities.is_read_only(obj): + return True + + return AXUtilities.is_focusable(obj) and not AXUtilities.is_editable(obj) + + def displayedText(self, obj): + """Returns the text being displayed for an object. + + Arguments: + - obj: the object + + Returns the text being displayed for an object or None if there isn't + any text being shown. + """ + + text = script_utilities.Utilities.displayedText(self, obj) + if text and text != self.EMBEDDED_OBJECT_CHARACTER: + return text + + if AXUtilities.is_link(obj) or AXUtilities.is_list_item(obj): + children = [x for x in AXObject.iter_children(obj)] + text = ' '.join(map(self.displayedText, children)) + if not text: + text = self.linkBasename(obj) + + return text + + def getLineContentsAtOffset(self, obj, offset, layoutMode=True, useCache=True): + return self.getObjectsFromEOCs( + obj, offset, Atspi.TextBoundaryType.LINE_START) + + def getObjectContentsAtOffset(self, obj, offset=0, useCache=True): + return self.getObjectsFromEOCs(obj, offset) + + def getObjectsFromEOCs(self, obj, offset=None, boundary=None): + """Breaks the string containing a mixture of text and embedded object + characters into a list of (obj, startOffset, endOffset, string) tuples. + + Arguments + - obj: the object whose EOCs we need to expand into tuples + - offset: the character offset. If None, use the current offset. + - boundary: the text boundary type. If None, get all text. + + Returns a list of (obj, startOffset, endOffset, string) tuples. + """ + + try: + text = obj.queryText() + htext = obj.queryHypertext() + except (AttributeError, NotImplementedError): + return [(obj, 0, 1, '')] + + string = text.getText(0, -1) + if not string: + return [(obj, 0, 1, '')] + + if offset is None: + offset = text.caretOffset + if boundary is None: + start = 0 + end = text.characterCount + else: + if boundary == Atspi.TextBoundaryType.CHAR: + key, mods = self.lastKeyAndModifiers() + if (mods & keybindings.SHIFT_MODIFIER_MASK) and key == 'Right': + offset -= 1 + segment, start, end = text.getTextAtOffset(offset, boundary) + + pattern = re.compile(self.EMBEDDED_OBJECT_CHARACTER) + offsets = [m.start(0) for m in re.finditer(pattern, string)] + offsets = [x for x in offsets if start <= x < end] + + objects = [] + try: + objs = [obj[htext.getLinkIndex(offset)] for offset in offsets] + except Exception: + objs = [] + ranges = [self.getHyperlinkRange(x) for x in objs] + for i, (first, last) in enumerate(ranges): + objects.append((obj, start, first, string[start:first])) + objects.append((objs[i], first, last, '')) + start = last + objects.append((obj, start, end, string[start:end])) + objects = [x for x in objects if x[1] < x[2]] + + return objects + + def findPreviousObject(self, obj): + """Finds the object before this one.""" + + if obj is None: + return None + + if AXUtilities.is_link(obj): + obj = AXObject.get_parent(obj) + + prevObj = AXObject.get_previous_object(obj) + if AXUtilities.is_list(prevObj) and AXObject.get_child_count(prevObj): + child = AXObject.get_child(prevObj, -1) + if self.isTextListItem(child): + prevObj = child + + return prevObj + + def findNextObject(self, obj): + """Finds the object after this one.""" + + if obj is None: + return None + + if AXUtilities.is_link(obj): + obj = AXObject.get_parent(obj) + + nextObj = AXObject.get_next_object(obj) + if AXUtilities.is_list(nextObj) and AXObject.get_child_count(nextObj): + child = AXObject.get_child(nextObj, 0) + if self.isTextListItem(child): + nextObj = child + + return nextObj + + def isTextListItem(self, obj): + """Returns True if obj is an item in a non-selectable list.""" + + if not AXUtilities.is_list_item(obj): + return False + + parent = AXObject.get_parent(obj) + if parent is None: + return False + + return not AXUtilities.is_focusable(parent) + + def isInlineContainer(self, obj): + """Returns True if obj is an inline/non-wrapped container.""" + + if AXUtilities.is_section(obj): + if AXObject.get_child_count(obj) > 1: + return self.onSameLine(AXObject.get_child(obj, 0), AXObject.get_child(obj, 1)) + return False + + if AXUtilities.is_list(obj): + if AXUtilities.is_focusable(obj): + return False + childCount = AXObject.get_child_count(obj) + if not childCount: + return AXObject.supports_text(obj) + if childCount == 1: + return False + return self.onSameLine(AXObject.get_child(obj, 0), AXObject.get_child(obj, 1)) + + return False + + def isEmbeddedDocument(self, obj): + if not self.isWebKitGtk(obj): + return False + + if not AXUtilities.is_document(obj): + return False + + parent = AXObject.get_parent(obj) + if not (parent and self.isWebKitGtk(parent)): + return False + + parent = AXObject.get_parent(parent) + if not (parent and not self.isWebKitGtk(parent)): + return False + + return True + + def setCaretAtStart(self, obj): + def implementsText(obj): + return not AXUtilities.is_list(obj) and AXObject.supports_text(obj) + + child = obj + if not implementsText(obj): + child = AXObject.find_descendant(obj, implementsText) + if not child: + return None, -1 + + index = -1 + text = child.queryText() + for i in range(text.characterCount): + if text.setCaretOffset(i): + index = i + break + + return child, index + + def treatAsBrowser(self, obj): + return self.isEmbeddedDocument(obj) + + def inDocumentContent(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + return self.isWebKitGtk(obj) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/speech_generator.py new file mode 100644 index 0000000..6f47e37 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/WebKitGtk/speech_generator.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs" \ + "Copyright (c) 2011-2012 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import cthulhu.keynames as keynames +import cthulhu.object_properties as object_properties +import cthulhu.settings as settings +import cthulhu.settings_manager as settings_manager +import cthulhu.speech_generator as speech_generator +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +######################################################################## +# # +# Custom SpeechGenerator # +# # +######################################################################## + +class SpeechGenerator(speech_generator.SpeechGenerator): + """Provides a speech generator specific to WebKitGtk widgets.""" + + def __init__(self, script): + speech_generator.SpeechGenerator.__init__(self, script) + + def getVoiceForString(self, obj, string, **args): + voice = settings.voices[settings.DEFAULT_VOICE] + if string.isupper(): + voice = settings.voices[settings.UPPERCASE_VOICE] + + return voice + + def _generateLabel(self, obj, **args): + result = super()._generateLabel(obj, **args) + if result or not self._script.utilities.isWebKitGtk(obj): + return result + + role = args.get('role', AXObject.get_role(obj)) + inferRoles = [Atspi.Role.CHECK_BOX, + Atspi.Role.COMBO_BOX, + Atspi.Role.ENTRY, + Atspi.Role.LIST, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.RADIO_BUTTON] + if role not in inferRoles: + return result + + label, objects = self._script.labelInference.infer(obj) + if label: + result.append(label) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + + return result + + def __generateHeadingRole(self, obj): + result = [] + role = Atspi.Role.HEADING + level = self._script.utilities.headingLevel(obj) + if level: + result.append(object_properties.ROLE_HEADING_LEVEL_SPEECH % { + 'role': self.getLocalizedRoleName(obj, role=role), + 'level': level}) + else: + result.append(self.getLocalizedRoleName(obj, role=role)) + + return result + + def _generateRoleName(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + role = args.get('role', AXObject.get_role(obj)) + force = args.get('force', False) + + doNotSpeak = [Atspi.Role.UNKNOWN] + if not force: + doNotSpeak.extend([Atspi.Role.FORM, + Atspi.Role.LABEL, + Atspi.Role.MENU_ITEM, + Atspi.Role.LIST_ITEM, + Atspi.Role.PARAGRAPH, + Atspi.Role.SECTION, + Atspi.Role.TABLE_CELL]) + + if role not in doNotSpeak: + if role == Atspi.Role.IMAGE: + link = AXObject.find_ancestor(obj, AXUtilities.is_link) + if link: + result.append(self.getLocalizedRoleName(link)) + elif role == Atspi.Role.HEADING: + result.extend(self.__generateHeadingRole(obj)) + else: + result.append(self.getLocalizedRoleName(obj, role=role)) + if AXObject.get_role(AXObject.get_parent(obj)) == Atspi.Role.HEADING: + result.extend(self.__generateHeadingRole(AXObject.get_parent(obj))) + + if result: + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + if role == Atspi.Role.LINK and AXObject.get_child_count(obj): + child = AXObject.get_child(obj, 0) + if not AXObject.get_role(child) == Atspi.Role.IMAGE: + return result + # If this is a link with a child which is an image, we + # want to indicate that. + # + result.append(self.getLocalizedRoleName(child)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + return result + + def _generateAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object. This is typically used to present the context for + an object (e.g., the names of the window, the panels, etc., + that the object is contained in). If the 'priorObj' attribute + of the args dictionary is set, only the differences in + ancestry between the 'priorObj' and the current obj will be + computed. The 'priorObj' is typically set by Cthulhu to be the + previous object with focus. + """ + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.LINK: + return [] + + args['stopAtRoles'] = [Atspi.Role.DOCUMENT_FRAME, + Atspi.Role.DOCUMENT_WEB, + Atspi.Role.EMBEDDED, + Atspi.Role.INTERNAL_FRAME, + Atspi.Role.FORM, + Atspi.Role.MENU_BAR, + Atspi.Role.TOOL_BAR] + args['skipRoles'] = [Atspi.Role.PARAGRAPH, + Atspi.Role.LIST_ITEM, + Atspi.Role.TEXT] + + return speech_generator.SpeechGenerator._generateAncestors( + self, obj, **args) + + def _generateMnemonic(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the mnemonic for the object, or + an empty array if no mnemonic can be found. + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not (_settingsManager.getSetting('enableMnemonicSpeaking') \ + or args.get('forceMnemonic', False)): + return [] + + if not self._script.utilities.isWebKitGtk(obj): + return speech_generator.SpeechGenerator._generateMnemonic( + self, obj, **args) + + result = [] + mnemonic, shortcut, accelerator = \ + self._script.utilities.mnemonicShortcutAccelerator(obj) + if shortcut: + if _settingsManager.getSetting('speechVerbosityLevel') == \ + settings.VERBOSITY_LEVEL_VERBOSE: + shortcut = f'Alt Shift {shortcut}' + result = [keynames.localizeKeySequence(shortcut)] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/__init__.py new file mode 100644 index 0000000..182fd90 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/__init__.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__all__ = ['clutter', + 'Chromium', + 'gtk', + 'GAIL', + 'Gecko', + 'J2SE-access-bridge', + 'Qt', + 'VCL.py', + 'WebKitGtk'] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/__init__.py new file mode 100644 index 0000000..91372dc --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script.py new file mode 100644 index 0000000..2393eec --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010-2013 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.scripts.default as default +from .script_utilities import Utilities + + +class Script(default.Script): + + def __init__(self, app): + default.Script.__init__(self, app) + + def getUtilities(self): + return Utilities(self) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script_utilities.py new file mode 100644 index 0000000..f2807b1 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/clutter/script_utilities.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.script_utilities as script_utilities + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + script_utilities.Utilities.__init__(self, script) + + def willEchoCharacter(self, event): + """Given a keyboard event containing an alphanumeric key, + determine if the script is likely to echo it as a character.""" + + # There is currently a bug in which we don't get the inserted text + # from the object:text-changed:insert event. We cannot echo what we + # don't receive. + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/__init__.py new file mode 100644 index 0000000..1cc055f --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/__init__.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script +from .script_utilities import Utilities diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script.py new file mode 100644 index 0000000..26f25ec --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013-2014 Igalia, S.L." +__license__ = "LGPL" + +import cthulhu.debug as debug +import cthulhu.cthulhu as cthulhu +import cthulhu.cthulhu_state as cthulhu_state +import cthulhu.scripts.default as default +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .script_utilities import Utilities + +class Script(default.Script): + + def __init__(self, app): + default.Script.__init__(self, app) + + def getUtilities(self): + return Utilities(self) + + def deactivate(self): + """Called when this script is deactivated.""" + + self.utilities.clearCachedObjects() + super().deactivate() + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if self.utilities.isToggleDescendantOfComboBox(newFocus): + newFocus = AXObject.find_ancestor(newFocus, AXUtilities.is_combo_box) or newFocus + cthulhu.setLocusOfFocus(event, newFocus, False) + elif self.utilities.isInOpenMenuBarMenu(newFocus): + window = self.utilities.topLevelObject(newFocus) + windowChanged = window and cthulhu_state.activeWindow != window + if windowChanged: + cthulhu.setActiveWindow(window) + + super().locusOfFocusChanged(event, oldFocus, newFocus) + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if not self.utilities.isTypeahead(cthulhu_state.locusOfFocus): + msg = "GTK: locusOfFocus is not typeahead. Passing along to default script." + debug.printMessage(debug.LEVEL_INFO, msg, True) + super().onActiveDescendantChanged(event) + return + + msg = "GTK: locusOfFocus believed to be typeahead. Presenting change." + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.presentObject(event.any_data, interrupt=True) + + def onCheckedChanged(self, event): + """Callback for object:state-changed:checked accessibility events.""" + + obj = event.source + if self.utilities.isSameObject(obj, cthulhu_state.locusOfFocus): + default.Script.onCheckedChanged(self, event) + return + + # Present changes of child widgets of GtkListBox items + if not AXObject.find_ancestor(obj, AXUtilities.is_list_box): + return + + self.presentObject(obj, alreadyFocused=True, interrupt=True) + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # NOTE: This event type is deprecated and Cthulhu should no longer use it. + # This callback remains just to handle bugs in applications and toolkits + # that fail to reliably emit object:state-changed:focused events. + + if self.utilities.eventIsCanvasNoise(event): + return + + if self.utilities.isLayoutOnly(event.source): + return + + if event.source == self.mouseReviewer.getCurrentItem(): + msg = "GTK: Event source is current mouse review item" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + if self.utilities.isTypeahead(cthulhu_state.locusOfFocus) \ + and AXObject.supports_table(event.source) \ + and not AXUtilities.is_focused(event.source): + return + + ancestor = AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.source) + if not ancestor: + cthulhu.setLocusOfFocus(event, event.source) + return + + if AXObject.supports_table(ancestor): + return + + if AXUtilities.is_menu(ancestor): + if AXUtilities.is_selected(cthulhu_state.locusOfFocus): + msg = "GTK: Event source is ancestor of selected focus. Ignoring." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + msg = "GTK: Event source is ancestor of unselected focus. Updating focus." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + cthulhu.setLocusOfFocus(event, event.source) + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if self.utilities.isUselessPanel(event.source): + msg = "GTK: Event source believed to be useless panel" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + super().onFocusedChanged(event) + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + if self.utilities.isEntryCompletionPopupItem(event.source): + if event.detail1: + cthulhu.setLocusOfFocus(event, event.source) + return + if cthulhu_state.locusOfFocus == event.source: + cthulhu.setLocusOfFocus(event, None) + return + + if AXUtilities.is_icon_or_canvas(event.source) \ + and self.utilities.handleContainerSelectionChange(AXObject.get_parent(event.source)): + return + + super().onSelectedChanged(event) + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if self.utilities.isComboBoxWithToggleDescendant(event.source) \ + and self.utilities.isOrDescendsFrom(cthulhu_state.locusOfFocus, event.source): + super().onSelectionChanged(event) + return + + isFocused = AXUtilities.is_focused(event.source) + if AXUtilities.is_combo_box(event.source) and not isFocused: + return + + if not isFocused and self.utilities.isTypeahead(cthulhu_state.locusOfFocus): + msg = "GTK: locusOfFocus believed to be typeahead. Presenting change." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + selectedChildren = self.utilities.selectedChildren(event.source) + for child in selectedChildren: + if not self.utilities.isLayoutOnly(child): + self.presentObject(child) + return + + if AXUtilities.is_layered_pane(event.source) \ + and self.utilities.selectedChildCount(event.source) > 1: + return + + super().onSelectionChanged(event) + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + if not event.detail1: + super().onShowingChanged(event) + return + + if self.utilities.isPopOver(event.source) \ + or AXUtilities.is_alert(event.source) \ + or AXUtilities.is_info_bar(event.source): + if AXUtilities.is_application(AXObject.get_parent(event.source)): + return + self.presentObject(event.source, interrupt=True) + return + + super().onShowingChanged(event) + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if not self.utilities.isShowingAndVisible(event.source): + tokens = ["GTK:", event.source, "is not showing and visible"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + super().onTextDeleted(event) + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if not self.utilities.isShowingAndVisible(event.source): + tokens = ["GTK:", event.source, "is not showing and visible"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return + + super().onTextInserted(event) + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + obj = event.source + if not self.utilities.isSameObject(obj, cthulhu_state.locusOfFocus): + return + + default.Script.onTextSelectionChanged(self, event) + + def isActivatableEvent(self, event): + if self.utilities.eventIsCanvasNoise(event): + return False + + if self.utilities.isUselessPanel(event.source): + return False + + return super().isActivatableEvent(event) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script_utilities.py new file mode 100644 index 0000000..4ffb7d4 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/toolkits/gtk/script_utilities.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2013-2014 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +import re + +import cthulhu.debug as debug +import cthulhu.script_utilities as script_utilities +import cthulhu.cthulhu_state as cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + super().__init__(script) + self._isComboBoxWithToggleDescendant = {} + self._isToggleDescendantOfComboBox = {} + self._isTypeahead = {} + self._isUselessPanel = {} + self._isLayoutOnly = {} + + def clearCachedObjects(self): + self._isComboBoxWithToggleDescendant = {} + self._isToggleDescendantOfComboBox = {} + self._isTypeahead = {} + self._isUselessPanel = {} + self._isLayoutOnly = {} + + def infoBar(self, root): + return AXObject.find_descendant(root, AXUtilities.is_info_bar) + + def isComboBoxWithToggleDescendant(self, obj): + if not AXUtilities.is_combo_box(obj): + return False + + rv = self._isComboBoxWithToggleDescendant.get(hash(obj)) + if rv is not None: + return rv + + for child in AXObject.iter_children(obj): + if not AXUtilities.is_filler(child): + continue + + toggle = AXObject.find_descendant(child, AXUtilities.is_toggle_button) + rv = toggle is not None + if toggle: + self._isToggleDescendantOfComboBox[hash(toggle)] = True + break + + self._isComboBoxWithToggleDescendant[hash(obj)] = rv + return rv + + def isLayoutOnly(self, obj): + rv = self._isLayoutOnly.get(hash(obj)) + if rv is not None: + if rv: + tokens = ["GTK:", obj, "is deemed to be layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + rv = super().isLayoutOnly(obj) + self._isLayoutOnly[hash(obj)] = rv + return rv + + def isToggleDescendantOfComboBox(self, obj): + if not AXUtilities.is_toggle_button(obj): + return False + + rv = self._isToggleDescendantOfComboBox.get(hash(obj)) + if rv is not None: + return rv + + comboBox = AXObject.find_ancestor(obj, AXUtilities.is_combo_box) + if comboBox: + self._isComboBoxWithToggleDescendant[hash(comboBox)] = True + + rv = comboBox is not None + self._isToggleDescendantOfComboBox[hash(obj)] = rv + return rv + + def isTypeahead(self, obj): + if not obj or AXObject.is_dead(obj): + return False + + if not AXUtilities.is_text(obj): + return False + + rv = self._isTypeahead.get(hash(obj)) + if rv is not None: + return rv + + parent = AXObject.get_parent(obj) + while parent and self.isLayoutOnly(parent): + parent = AXObject.get_parent(parent) + + rv = AXUtilities.is_window(parent) + self._isTypeahead[hash(obj)] = rv + return rv + + def isSearchEntry(self, obj, focusedOnly=False): + # Another example of why we need subrole support in ATK and AT-SPI2. + if not (AXObject.get_name(obj) and AXUtilities.is_single_line(obj)): + return False + + if focusedOnly and not AXUtilities.is_focused(obj): + return False + + icons = [x for x in AXObject.iter_children(obj, AXUtilities.is_icon)] + if icons: + return True + + return False + + def isEntryCompletionPopupItem(self, obj): + return AXUtilities.is_table_cell(obj) \ + and AXObject.find_ancestor(obj, AXUtilities.is_window) is not None + + def isPopOver(self, obj): + return AXObject.has_relation(obj, Atspi.RelationType.POPUP_FOR) + + def isSameObject(self, obj1, obj2, comparePaths=False, ignoreNames=False, + ignoreDescriptions=True): + return super().isSameObject(obj1, obj2, comparePaths, ignoreNames, False) + + def isUselessPanel(self, obj): + if not AXUtilities.is_panel(obj): + return False + + rv = self._isUselessPanel.get(hash(obj)) + if rv is not None: + return rv + + childCount = AXObject.get_child_count(obj) + name = AXObject.get_name(obj) + rv = not (name or childCount or AXObject.supports_text(obj)) + self._isUselessPanel[hash(obj)] = rv + return rv + + def rgbFromString(self, attributeValue): + regex = re.compile(r"rgb|[^\w,]", re.IGNORECASE) + string = re.sub(regex, "", attributeValue) + red, green, blue = string.split(",") + + return int(red) >> 8, int(green) >> 8, int(blue) >> 8 + + def isZombie(self, obj): + rv = super().isZombie(obj) + if rv and self.isLink(obj) and AXObject.get_index_in_parent(obj) == -1: + tokens = ["GTK: Hacking around bug 759736 for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return rv + + def eventIsCanvasNoise(self, event): + if not AXUtilities.is_canvas(event.source): + return False + + if not cthulhu_state.activeWindow: + msg = "GTK: No active window" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + topLevel = self.topLevelObject(event.source) + if not self.isSameObject(topLevel, cthulhu_state.activeWindow): + msg = "GTK: Event is believed to be canvas noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def _adjustPointForObj(self, obj, x, y, coordType): + if not AXUtilities.is_single_line(obj) \ + or not AXObject.supports_editable_text(obj): + return x, y + + text = self.queryNonEmptyText(obj) + if not text: + return x, y + + objBox = obj.queryComponent().getExtents(coordType) + stringBox = text.getRangeExtents(0, text.characterCount, coordType) + if self.intersection(objBox, stringBox) != (0, 0, 0, 0): + return x, y + + tokens = ["GTK: text bounds", stringBox, "not in obj bounds", objBox] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # This is where the string starts; not the widget. + boxX, boxY = stringBox[0], stringBox[1] + + # Window Coordinates should be relative to the window; not the widget. + # But broken interface is broken, and this appears to be what is being + # exposed. And we need this information to get the widget's x and y. + charExtents = text.getCharacterExtents(0, Atspi.CoordType.WINDOW) + if 0 < charExtents[0] < charExtents[2]: + boxX -= charExtents[0] + if 0 < charExtents[1] < charExtents[3]: + boxY -= charExtents[1] + + # The point relative to the widget: + relX = x - objBox[0] + relY = y - objBox[1] + + # The point relative to our adjusted bounding box: + newX = boxX + relX + newY = boxY + relY + + msg = f"GTK: Adjusted ({x}, {y}) to ({newX}, {newY})" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return newX, newY diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/__init__.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/__init__.py new file mode 100644 index 0000000..be2a0f6 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/__init__.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +from .script import Script +from .speech_generator import SpeechGenerator +from .braille_generator import BrailleGenerator +from .script_utilities import Utilities +from .tutorial_generator import TutorialGenerator diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/bookmarks.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/bookmarks.py new file mode 100644 index 0000000..5610f75 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/bookmarks.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +from cthulhu import bookmarks +from cthulhu import messages + + +class Bookmarks(bookmarks.Bookmarks): + + def __init__(self, script): + super().__init__(script) + self._currentbookmarkindex = {} + + def addBookmark(self, script, inputEvent): + """Add an in-page accessible object bookmark for this key and URI.""" + + index = (inputEvent.hw_code, self.getURIKey()) + obj, characterOffset = self._script.utilities.getCaretContext() + path = self._objToPath() + self._bookmarks[index] = path, characterOffset + self._script.presentMessage(messages.BOOKMARK_ENTERED) + + def goToBookmark(self, script, inputEvent, index=None): + """Go to the bookmark indexed at this key and this page's URI.""" + + index = index or (inputEvent.hw_code, self.getURIKey()) + try: + path, offset = self._bookmarks[index] + except KeyError: + self._script.systemBeep() + return + + obj = self.pathToObj(path) + if not obj: + self._script.systemBeep() + return + + self._script.utilities.setCaretPosition(obj, offset) + contents = self._script.utilities.getObjectContentsAtOffset(obj, offset) + self._script.speakContents(contents) + self._script.displayContents(contents) + self._currentbookmarkindex[index[1]] = index[0] + + def saveBookmarks(self, script, inputEvent): + """Save the bookmarks for this script.""" + + saved = {} + for index, bookmark in self._bookmarks.items(): + saved[index] = bookmark[0], bookmark[1] + + try: + self.saveBookmarksToDisk(saved) + self._script.presentMessage(messages.BOOKMARKS_SAVED) + except IOError: + self._script.presentMessage(messages.BOOKMARKS_SAVED_FAILURE) + + for o in self._saveObservers: + o() + + def goToNextBookmark(self, script, inputEvent): + """Go to the next bookmark location.""" + + # The convenience of using a dictionary to add/goto a bookmark is offset + # by the difficulty in finding the next bookmark. We will need to sort + # our keys to determine the next bookmark on a page-by-page basis. + bm_keys = list(self._bookmarks.keys()) + current_uri = self.getURIKey() + + # mine out the hardware keys for this page and sort them + thispage_hwkeys = [] + for bm_key in bm_keys: + if bm_key[1] == current_uri: + thispage_hwkeys.append(bm_key[0]) + thispage_hwkeys.sort() + + if len(thispage_hwkeys) == 0: + self._script.systemBeep() + return + + if len(thispage_hwkeys) == 1 or current_uri not in self._currentbookmarkindex: + self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri)) + return + + try: + index = thispage_hwkeys.index(self._currentbookmarkindex[current_uri]) + self.goToBookmark(None, index=(thispage_hwkeys[index+1], current_uri)) + except (ValueError, KeyError, IndexError): + self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri)) + + def goToPrevBookmark(self, script, inputEvent): + """Go to the previous bookmark location.""" + + bm_keys = list(self._bookmarks.keys()) + current_uri = self.getURIKey() + + # mine out the hardware keys for this page and sort them + thispage_hwkeys = [] + for bm_key in bm_keys: + if bm_key[1] == current_uri: + thispage_hwkeys.append(bm_key[0]) + thispage_hwkeys.sort() + + if len(thispage_hwkeys) == 0: + self._script.systemBeep() + return + + if len(thispage_hwkeys) == 1 or current_uri not in self._currentbookmarkindex: + self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri)) + return + + try: + index = thispage_hwkeys.index(self._currentbookmarkindex[current_uri]) + self.goToBookmark(None, index=(thispage_hwkeys[index-1], current_uri)) + except (ValueError, KeyError, IndexError): + self.goToBookmark(None, index=(thispage_hwkeys[0], current_uri)) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/braille_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/braille_generator.py new file mode 100644 index 0000000..deec6b1 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/braille_generator.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2011 Cthulhu Team" \ + "Copyright (c) 2011-2015 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import braille +from cthulhu import braille_generator +from cthulhu import debug +from cthulhu import messages +from cthulhu import object_properties +from cthulhu import cthulhu_state +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + + +class BrailleGenerator(braille_generator.BrailleGenerator): + + def __init__(self, script): + super().__init__(script) + + def getLocalizedRoleName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super().getLocalizedRoleName(obj, **args) + + roledescription = self._script.utilities.getRoleDescription(obj, True) + if roledescription: + return roledescription + + return super().getLocalizedRoleName(obj, **args) + + def _generateRoleName(self, obj, **args): + """Prevents some roles from being displayed.""" + + if not self._script.utilities.inDocumentContent(obj): + return super()._generateRoleName(obj, **args) + + roledescription = self._script.utilities.getRoleDescription(obj, True) + if roledescription: + return [roledescription] + + doNotDisplay = [Atspi.Role.FORM, + Atspi.Role.PARAGRAPH, + Atspi.Role.STATIC, + Atspi.Role.SECTION, + Atspi.Role.REDUNDANT_OBJECT, + Atspi.Role.UNKNOWN] + + if not AXUtilities.is_focusable(obj): + doNotDisplay.extend([Atspi.Role.LIST, + Atspi.Role.LIST_ITEM, + Atspi.Role.COLUMN_HEADER, + Atspi.Role.ROW_HEADER, + Atspi.Role.TABLE_CELL, + Atspi.Role.PANEL]) + + if args.get('startOffset') is not None and args.get('endOffset') is not None: + doNotDisplay.append(Atspi.Role.ALERT) + + result = [] + role = args.get('role', AXObject.get_role(obj)) + + if role == Atspi.Role.HEADING: + level = self._script.utilities.headingLevel(obj) + result.append(object_properties.ROLE_HEADING_LEVEL_BRAILLE % level) + + elif self._script.utilities.isLink(obj) and obj == cthulhu_state.locusOfFocus: + if AXUtilities.is_image(AXObject.get_parent(obj)): + result.append(messages.IMAGE_MAP_LINK) + + elif role not in doNotDisplay: + label = self._script.utilities.labelForCellCoordinates(obj) + if label: + result.append(label) + else: + result = super()._generateRoleName(obj, **args) + + index = args.get('index', 0) + total = args.get('total', 1) + if index == total - 1 and role != Atspi.Role.HEADING \ + and (role == Atspi.Role.IMAGE or self._script.utilities.queryNonEmptyText(obj)): + heading = AXObject.find_ancestor(obj, AXUtilities.is_heading) + if heading is not None: + result.extend(self._generateRoleName(heading)) + + return result + + def _generateLabelOrName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateLabelOrName(obj, **args) + + if self._script.utilities.isTextBlockElement(obj): + return [] + + if AXUtilities.is_editable(obj) \ + and self._script.utilities.isCodeDescendant(obj): + return [] + + return self._generateName(obj, **args) + + def _generateLabel(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateLabel(obj, **args) + + label, objects = self._script.utilities.inferLabelFor(obj) + if label: + return [label] + + return super()._generateLabel(obj, **args) + + def _generateLabelAndName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateLabelAndName(obj, **args) + + if self._script.utilities.isTextBlockElement(obj): + return [] + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.LABEL and AXObject.supports_text(obj): + return [] + + return super()._generateLabelAndName(obj, **args) + + def _generateDescription(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateDescription(obj, **args) + + if self._script.utilities.preferDescriptionOverName(obj): + return [] + + return super()._generateDescription(obj, **args) + + def _generateName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateName(obj, **args) + + brailleLabel = self._script.utilities.objectAttributes(obj).get("braillelabel") + if brailleLabel: + return [brailleLabel] + + if self._script.utilities.preferDescriptionOverName(obj): + return [AXObject.get_description(obj)] + + if AXObject.get_name(obj) and not self._script.utilities.hasValidName(obj): + return [] + + result = super()._generateName(obj, **args) + if result and result[0] and not self._script.utilities.hasExplicitName(obj): + result[0] = result[0].strip() + elif not result and AXUtilities.is_check_box(obj): + gridCell = AXObject.find_ancestor(obj, self._script.utilities.isGridCell) + if gridCell: + return super()._generateName(gridCell, **args) + + return result + + def _generateExpandedEOCs(self, obj, **args): + """Returns the expanded embedded object characters for an object.""" + + if not self._script.utilities.inDocumentContent(obj): + return super()._generateExpandedEOCs(obj, **args) + + result = [] + startOffset = args.get('startOffset', 0) + endOffset = args.get('endOffset', -1) + text = self._script.utilities.expandEOCs(obj, startOffset, endOffset) + if text: + result.append(text) + + return result + + def _generateRealActiveDescendantDisplayedText(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateRealActiveDescendantDisplayedText(obj, **args) + + rad = self._script.utilities.realActiveDescendant(obj) + return self._generateDisplayedText(rad, **args) + + def _generateTableCellRow(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateTableCellRow(obj, **args) + + if not self._script.utilities.shouldReadFullRow(obj): + return self._generateRealTableCell(obj, **args) + + row = AXObject.find_ancestor(obj, AXUtilities.is_table_row) + if row and AXObject.get_name(row) and not self._script.utilities.isLayoutOnly(row): + return self.generate(row, includeContext=False) + + return super()._generateTableCellRow(obj, **args) + + def generateBraille(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + tokens = ["WEB:", obj, "is not in document content. Calling default braille generator."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return super().generateBraille(obj, **args) + + tokens = ["WEB: Generating braille for document object", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + result = [] + + args['includeContext'] = not self._script.utilities.inDocumentContent(obj) + oldRole = None + if self._script.utilities.isClickableElement(obj) \ + or self._script.utilities.isLink(obj): + oldRole = self._overrideRole(Atspi.Role.LINK, args) + elif self._script.utilities.isCustomImage(obj): + oldRole = self._overrideRole(Atspi.Role.IMAGE, args) + elif self._script.utilities.isAnchor(obj): + oldRole = self._overrideRole(Atspi.Role.STATIC, args) + elif self._script.utilities.treatAsDiv(obj, offset=args.get('startOffset')): + oldRole = self._overrideRole(Atspi.Role.SECTION, args) + elif self._script.utilities.treatAsEntry(obj): + oldRole = self._overrideRole(Atspi.Role.ENTRY, args) + + if AXUtilities.is_menu_item(obj): + comboBox = AXObject.find_ancestor(obj, AXUtilities.is_combo_box) + if comboBox and not AXUtilities.is_expanded(comboBox): + obj = comboBox + result.extend(super().generateBraille(obj, **args)) + del args['includeContext'] + if oldRole: + self._restoreRole(oldRole, args) + + return result + + def _generateEol(self, obj, **args): + if self._script.utilities.isContentEditableWithEmbeddedObjects(obj): + return [] + + if AXUtilities.is_editable(obj) \ + or not self._script.utilities.inDocumentContent(obj): + return super()._generateEol(obj, **args) + + return [] + + def generateContents(self, contents, **args): + if not len(contents): + return [] + + result = [] + contents = self._script.utilities.filterContentsForPresentation(contents, True) + + document = args.get("documentFrame") + obj, offset = self._script.utilities.getCaretContext(documentFrame=document) + index = self._script.utilities.findObjectInContents(obj, offset, contents) + + lastRegion = None + focusedRegion = None + for i, content in enumerate(contents): + acc, start, end, string = content + regions, fRegion = self.generateBraille( + acc, startOffset=start, endOffset=end, string=string, + index=i, total=len(contents)) + if not regions: + continue + + if i == index: + focusedRegion = fRegion + + if lastRegion and regions: + if lastRegion.string: + lastChar = lastRegion.string[-1] + else: + lastChar = "" + if regions[0].string: + nextChar = regions[0].string[0] + else: + nextChar = "" + if self._script.utilities.needsSeparator(lastChar, nextChar): + regions.insert(0, braille.Region(" ")) + + lastRegion = regions[-1] + result.append(regions) + + return result, focusedRegion diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script.py new file mode 100644 index 0000000..e7bb127 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script.py @@ -0,0 +1,2774 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010 Cthulhu Team." \ + "Copyright (c) 2014-2015 Igalia, S.L." +__license__ = "LGPL" + +import time +from gi.repository import Gtk + +from cthulhu import caret_navigation +from cthulhu import cmdnames +from cthulhu import keybindings +from cthulhu import debug +from cthulhu import guilabels +from cthulhu import input_event +from cthulhu import liveregions +from cthulhu import messages +from cthulhu import cthulhu +from cthulhu import cthulhu_state +from cthulhu import settings +from cthulhu import settings_manager +from cthulhu import speech +from cthulhu import speechserver +from cthulhu import structural_navigation +from cthulhu.acss import ACSS +from cthulhu.scripts import default +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +from .bookmarks import Bookmarks +from .braille_generator import BrailleGenerator +from .sound_generator import SoundGenerator +from .speech_generator import SpeechGenerator +from .tutorial_generator import TutorialGenerator +from .script_utilities import Utilities + +_settingsManager = settings_manager.getManager() + + +class Script(default.Script): + + def __init__(self, app): + super().__init__(app) + + self._sayAllContents = [] + self._inSayAll = False + self._sayAllIsInterrupted = False + self._loadingDocumentContent = False + self._madeFindAnnouncement = False + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = False + self._lastMouseButtonContext = None, -1 + self._lastMouseOverObject = None + self._preMouseOverContext = None, -1 + self._inMouseOverObject = False + self._inFocusMode = False + self._focusModeIsSticky = False + self._browseModeIsSticky = False + + if _settingsManager.getSetting('caretNavigationEnabled') is None: + _settingsManager.setSetting('caretNavigationEnabled', True) + if _settingsManager.getSetting('sayAllOnLoad') is None: + _settingsManager.setSetting('sayAllOnLoad', True) + if _settingsManager.getSetting('pageSummaryOnLoad') is None: + _settingsManager.setSetting('pageSummaryOnLoad', True) + + self._changedLinesOnlyCheckButton = None + self._controlCaretNavigationCheckButton = None + self._minimumFindLengthAdjustment = None + self._minimumFindLengthLabel = None + self._minimumFindLengthSpinButton = None + self._pageSummaryOnLoadCheckButton = None + self._sayAllOnLoadCheckButton = None + self._skipBlankCellsCheckButton = None + self._speakCellCoordinatesCheckButton = None + self._speakCellHeadersCheckButton = None + self._speakCellSpanCheckButton = None + self._speakResultsDuringFindCheckButton = None + self._structuralNavigationCheckButton = None + self._autoFocusModeStructNavCheckButton = None + self._autoFocusModeCaretNavCheckButton = None + self._autoFocusModeNativeNavCheckButton = None + self._layoutModeCheckButton = None + + self.attributeNamesDict["invalid"] = "text-spelling" + self.attributeNamesDict["text-align"] = "justification" + self.attributeNamesDict["text-indent"] = "indent" + + def deactivate(self): + """Called when this script is deactivated.""" + + self._sayAllContents = [] + self._inSayAll = False + self._sayAllIsInterrupted = False + self._loadingDocumentContent = False + self._madeFindAnnouncement = False + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = False + self._lastMouseButtonContext = None, -1 + self._lastMouseOverObject = None + self._preMouseOverContext = None, -1 + self._inMouseOverObject = False + self.utilities.clearCachedObjects() + self.removeKeyGrabs() + + def getAppKeyBindings(self): + """Returns the application-specific keybindings for this script.""" + + keyBindings = keybindings.KeyBindings() + + structNavBindings = self.structuralNavigation.keyBindings + for keyBinding in structNavBindings.keyBindings: + keyBindings.add(keyBinding) + + caretNavBindings = self.caretNavigation.get_bindings() + for keyBinding in caretNavBindings.keyBindings: + keyBindings.add(keyBinding) + + liveRegionBindings = self.liveRegionManager.keyBindings + for keyBinding in liveRegionBindings.keyBindings: + keyBindings.add(keyBinding) + + keyBindings.add( + keybindings.KeyBinding( + "a", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers.get("togglePresentationModeHandler"))) + + keyBindings.add( + keybindings.KeyBinding( + "a", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers.get("enableStickyFocusModeHandler"), + 2)) + + keyBindings.add( + keybindings.KeyBinding( + "a", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers.get("enableStickyBrowseModeHandler"), + 3)) + + keyBindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self.inputEventHandlers.get("toggleLayoutModeHandler"))) + + + layout = _settingsManager.getSetting('keyboardLayout') + if layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP: + key = "KP_Multiply" + else: + key = "0" + + keyBindings.add( + keybindings.KeyBinding( + key, + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers.get("moveToMouseOverHandler"))) + + return keyBindings + + def setupInputEventHandlers(self): + """Defines InputEventHandlers for this script.""" + + super().setupInputEventHandlers() + self.inputEventHandlers.update( + self.structuralNavigation.inputEventHandlers) + + self.inputEventHandlers.update( + self.caretNavigation.get_handlers()) + + self.inputEventHandlers.update( + self.liveRegionManager.inputEventHandlers) + + self.inputEventHandlers["sayAllHandler"] = \ + input_event.InputEventHandler( + Script.sayAll, + cmdnames.SAY_ALL) + + self.inputEventHandlers["panBrailleLeftHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleLeft, + cmdnames.PAN_BRAILLE_LEFT, + False) # Do not enable learn mode for this action + + self.inputEventHandlers["panBrailleRightHandler"] = \ + input_event.InputEventHandler( + Script.panBrailleRight, + cmdnames.PAN_BRAILLE_RIGHT, + False) # Do not enable learn mode for this action + + self.inputEventHandlers["moveToMouseOverHandler"] = \ + input_event.InputEventHandler( + Script.moveToMouseOver, + cmdnames.MOUSE_OVER_MOVE) + + self.inputEventHandlers["togglePresentationModeHandler"] = \ + input_event.InputEventHandler( + Script.togglePresentationMode, + cmdnames.TOGGLE_PRESENTATION_MODE) + + self.inputEventHandlers["enableStickyFocusModeHandler"] = \ + input_event.InputEventHandler( + Script.enableStickyFocusMode, + cmdnames.SET_FOCUS_MODE_STICKY) + + self.inputEventHandlers["enableStickyBrowseModeHandler"] = \ + input_event.InputEventHandler( + Script.enableStickyBrowseMode, + cmdnames.SET_BROWSE_MODE_STICKY) + + self.inputEventHandlers["toggleLayoutModeHandler"] = \ + input_event.InputEventHandler( + Script.toggleLayoutMode, + cmdnames.TOGGLE_LAYOUT_MODE) + + self.inputEventHandlers["activateClickableHandler"] = \ + input_event.InputEventHandler( + Script.activateClickableElement, + "Activate clickable element") + + + def getBookmarks(self): + """Returns the "bookmarks" class for this script.""" + + try: + return self.bookmarks + except AttributeError: + self.bookmarks = Bookmarks(self) + return self.bookmarks + + def getBrailleGenerator(self): + """Returns the braille generator for this script.""" + + return BrailleGenerator(self) + + def getCaretNavigation(self): + """Returns the caret navigation support for this script.""" + + return caret_navigation.CaretNavigation(self) + + def getEnabledStructuralNavigationTypes(self): + """Returns the structural navigation object types for this script.""" + + return [structural_navigation.StructuralNavigation.BLOCKQUOTE, + structural_navigation.StructuralNavigation.BUTTON, + structural_navigation.StructuralNavigation.CHECK_BOX, + structural_navigation.StructuralNavigation.CHUNK, + structural_navigation.StructuralNavigation.CLICKABLE, + structural_navigation.StructuralNavigation.COMBO_BOX, + structural_navigation.StructuralNavigation.CONTAINER, + structural_navigation.StructuralNavigation.ENTRY, + structural_navigation.StructuralNavigation.FORM_FIELD, + structural_navigation.StructuralNavigation.HEADING, + structural_navigation.StructuralNavigation.IFRAME, + structural_navigation.StructuralNavigation.IMAGE, + structural_navigation.StructuralNavigation.LANDMARK, + structural_navigation.StructuralNavigation.LINK, + structural_navigation.StructuralNavigation.LIST, + structural_navigation.StructuralNavigation.LIST_ITEM, + structural_navigation.StructuralNavigation.LIVE_REGION, + structural_navigation.StructuralNavigation.PARAGRAPH, + structural_navigation.StructuralNavigation.RADIO_BUTTON, + structural_navigation.StructuralNavigation.SEPARATOR, + structural_navigation.StructuralNavigation.TABLE, + structural_navigation.StructuralNavigation.TABLE_CELL, + structural_navigation.StructuralNavigation.UNVISITED_LINK, + structural_navigation.StructuralNavigation.VISITED_LINK] + + def getLiveRegionManager(self): + """Returns the live region support for this script.""" + + return liveregions.LiveRegionManager(self) + + def getSoundGenerator(self): + """Returns the sound generator for this script.""" + + return SoundGenerator(self) + + def getSpeechGenerator(self): + """Returns the speech generator for this script.""" + + return SpeechGenerator(self) + + def getTutorialGenerator(self): + """Returns the tutorial generator for this script.""" + + return TutorialGenerator(self) + + def getUtilities(self): + """Returns the utilities for this script.""" + + return Utilities(self) + + def getAppPreferencesGUI(self): + """Return a GtkGrid containing app-unique configuration items.""" + + grid = Gtk.Grid() + grid.set_border_width(12) + + generalFrame = Gtk.Frame() + grid.attach(generalFrame, 0, 0, 1, 1) + + label = Gtk.Label(label=f"{guilabels.PAGE_NAVIGATION}") + label.set_use_markup(True) + generalFrame.set_label_widget(label) + + generalAlignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) + generalAlignment.set_padding(0, 0, 12, 0) + generalFrame.add(generalAlignment) + generalGrid = Gtk.Grid() + generalAlignment.add(generalGrid) + + label = guilabels.USE_CARET_NAVIGATION + value = _settingsManager.getSetting('caretNavigationEnabled') + self._controlCaretNavigationCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._controlCaretNavigationCheckButton.set_active(value) + generalGrid.attach(self._controlCaretNavigationCheckButton, 0, 0, 1, 1) + + label = guilabels.AUTO_FOCUS_MODE_CARET_NAV + value = _settingsManager.getSetting('caretNavTriggersFocusMode') + self._autoFocusModeCaretNavCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self._autoFocusModeCaretNavCheckButton.set_active(value) + generalGrid.attach(self._autoFocusModeCaretNavCheckButton, 0, 1, 1, 1) + + label = guilabels.USE_STRUCTURAL_NAVIGATION + value = self.structuralNavigation.enabled + self._structuralNavigationCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._structuralNavigationCheckButton.set_active(value) + generalGrid.attach(self._structuralNavigationCheckButton, 0, 2, 1, 1) + + label = guilabels.AUTO_FOCUS_MODE_STRUCT_NAV + value = _settingsManager.getSetting('structNavTriggersFocusMode') + self._autoFocusModeStructNavCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self._autoFocusModeStructNavCheckButton.set_active(value) + generalGrid.attach(self._autoFocusModeStructNavCheckButton, 0, 3, 1, 1) + + label = guilabels.AUTO_FOCUS_MODE_NATIVE_NAV + value = _settingsManager.getSetting('nativeNavTriggersFocusMode') + self._autoFocusModeNativeNavCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self._autoFocusModeNativeNavCheckButton.set_active(value) + generalGrid.attach(self._autoFocusModeNativeNavCheckButton, 0, 4, 1, 1) + + label = guilabels.READ_PAGE_UPON_LOAD + value = _settingsManager.getSetting('sayAllOnLoad') + self._sayAllOnLoadCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self._sayAllOnLoadCheckButton.set_active(value) + generalGrid.attach(self._sayAllOnLoadCheckButton, 0, 5, 1, 1) + + label = guilabels.PAGE_SUMMARY_UPON_LOAD + value = _settingsManager.getSetting('pageSummaryOnLoad') + self._pageSummaryOnLoadCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self._pageSummaryOnLoadCheckButton.set_active(value) + generalGrid.attach(self._pageSummaryOnLoadCheckButton, 0, 6, 1, 1) + + label = guilabels.CONTENT_LAYOUT_MODE + value = _settingsManager.getSetting('layoutMode') + self._layoutModeCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self._layoutModeCheckButton.set_active(value) + generalGrid.attach(self._layoutModeCheckButton, 0, 7, 1, 1) + + tableFrame = Gtk.Frame() + grid.attach(tableFrame, 0, 1, 1, 1) + + label = Gtk.Label(label=f"{guilabels.TABLE_NAVIGATION}") + label.set_use_markup(True) + tableFrame.set_label_widget(label) + + tableAlignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) + tableAlignment.set_padding(0, 0, 12, 0) + tableFrame.add(tableAlignment) + tableGrid = Gtk.Grid() + tableAlignment.add(tableGrid) + + label = guilabels.TABLE_SPEAK_CELL_COORDINATES + value = _settingsManager.getSetting('speakCellCoordinates') + self._speakCellCoordinatesCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._speakCellCoordinatesCheckButton.set_active(value) + tableGrid.attach(self._speakCellCoordinatesCheckButton, 0, 0, 1, 1) + + label = guilabels.TABLE_SPEAK_CELL_SPANS + value = _settingsManager.getSetting('speakCellSpan') + self._speakCellSpanCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._speakCellSpanCheckButton.set_active(value) + tableGrid.attach(self._speakCellSpanCheckButton, 0, 1, 1, 1) + + label = guilabels.TABLE_ANNOUNCE_CELL_HEADER + value = _settingsManager.getSetting('speakCellHeaders') + self._speakCellHeadersCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._speakCellHeadersCheckButton.set_active(value) + tableGrid.attach(self._speakCellHeadersCheckButton, 0, 2, 1, 1) + + label = guilabels.TABLE_SKIP_BLANK_CELLS + value = _settingsManager.getSetting('skipBlankCells') + self._skipBlankCellsCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._skipBlankCellsCheckButton.set_active(value) + tableGrid.attach(self._skipBlankCellsCheckButton, 0, 3, 1, 1) + + findFrame = Gtk.Frame() + grid.attach(findFrame, 0, 2, 1, 1) + + label = Gtk.Label(label=f"{guilabels.FIND_OPTIONS}") + label.set_use_markup(True) + findFrame.set_label_widget(label) + + findAlignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) + findAlignment.set_padding(0, 0, 12, 0) + findFrame.add(findAlignment) + findGrid = Gtk.Grid() + findAlignment.add(findGrid) + + verbosity = _settingsManager.getSetting('findResultsVerbosity') + + label = guilabels.FIND_SPEAK_RESULTS + value = verbosity != settings.FIND_SPEAK_NONE + self._speakResultsDuringFindCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._speakResultsDuringFindCheckButton.set_active(value) + findGrid.attach(self._speakResultsDuringFindCheckButton, 0, 0, 1, 1) + + label = guilabels.FIND_ONLY_SPEAK_CHANGED_LINES + value = verbosity == settings.FIND_SPEAK_IF_LINE_CHANGED + self._changedLinesOnlyCheckButton = \ + Gtk.CheckButton.new_with_mnemonic(label) + self._changedLinesOnlyCheckButton.set_active(value) + findGrid.attach(self._changedLinesOnlyCheckButton, 0, 1, 1, 1) + + hgrid = Gtk.Grid() + findGrid.attach(hgrid, 0, 2, 1, 1) + + self._minimumFindLengthLabel = \ + Gtk.Label(label=guilabels.FIND_MINIMUM_MATCH_LENGTH) + self._minimumFindLengthLabel.set_alignment(0, 0.5) + hgrid.attach(self._minimumFindLengthLabel, 0, 0, 1, 1) + + self._minimumFindLengthAdjustment = \ + Gtk.Adjustment(_settingsManager.getSetting( + 'findResultsMinimumLength'), 0, 20, 1) + self._minimumFindLengthSpinButton = Gtk.SpinButton() + self._minimumFindLengthSpinButton.set_adjustment( + self._minimumFindLengthAdjustment) + hgrid.attach(self._minimumFindLengthSpinButton, 1, 0, 1, 1) + self._minimumFindLengthLabel.set_mnemonic_widget( + self._minimumFindLengthSpinButton) + + grid.show_all() + return grid + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + if not self._speakResultsDuringFindCheckButton.get_active(): + verbosity = settings.FIND_SPEAK_NONE + elif self._changedLinesOnlyCheckButton.get_active(): + verbosity = settings.FIND_SPEAK_IF_LINE_CHANGED + else: + verbosity = settings.FIND_SPEAK_ALL + + return { + 'findResultsVerbosity': verbosity, + 'findResultsMinimumLength': self._minimumFindLengthSpinButton.get_value(), + 'sayAllOnLoad': self._sayAllOnLoadCheckButton.get_active(), + 'pageSummaryOnLoad': self._pageSummaryOnLoadCheckButton.get_active(), + 'structuralNavigationEnabled': self._structuralNavigationCheckButton.get_active(), + 'structNavTriggersFocusMode': self._autoFocusModeStructNavCheckButton.get_active(), + 'caretNavigationEnabled': self._controlCaretNavigationCheckButton.get_active(), + 'caretNavTriggersFocusMode': self._autoFocusModeCaretNavCheckButton.get_active(), + 'nativeNavTriggersFocusMode': self._autoFocusModeNativeNavCheckButton.get_active(), + 'speakCellCoordinates': self._speakCellCoordinatesCheckButton.get_active(), + 'layoutMode': self._layoutModeCheckButton.get_active(), + 'speakCellSpan': self._speakCellSpanCheckButton.get_active(), + 'speakCellHeaders': self._speakCellHeadersCheckButton.get_active(), + 'skipBlankCells': self._skipBlankCellsCheckButton.get_active() + } + + def skipObjectEvent(self, event): + """Returns True if this object event should be skipped.""" + + if event.type.startswith('object:state-changed:focused') and event.detail1: + if AXUtilities.is_link(event.source): + return False + elif event.type.startswith('object:children-changed'): + if AXUtilities.is_dialog(event.any_data): + return False + + return super().skipObjectEvent(event) + + def presentationInterrupt(self): + super().presentationInterrupt() + msg = "WEB: Flushing live region messages" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.liveRegionManager.flushMessages() + + def consumesKeyboardEvent(self, keyboardEvent): + """Returns True if the script will consume this keyboard event.""" + + # We need to do this here. Cthulhu caret and structural navigation + # often result in the user being repositioned without our getting + # a corresponding AT-SPI event. Without an AT-SPI event, script.py + # won't know to dump the generator cache. See bgo#618827. + self.generatorCache = {} + + self._lastMouseButtonContext = None, -1 + + handler = self.keyBindings.getInputHandler(keyboardEvent) + if handler and self.caretNavigation.handles_navigation(handler): + consumes = self.useCaretNavigationModel(keyboardEvent) + self._lastCommandWasCaretNav = consumes + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = False + return consumes + + if handler and handler.function in self.structuralNavigation.functions: + consumes = self.useStructuralNavigationModel() + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = consumes + self._lastCommandWasMouseButton = False + return consumes + + if handler and handler.function in self.liveRegionManager.functions: + # This is temporary. + consumes = self.useStructuralNavigationModel() + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = consumes + self._lastCommandWasMouseButton = False + return consumes + + if not keyboardEvent.isModifierKey(): + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = False + + # Check parent first + consumes = super().consumesKeyboardEvent(keyboardEvent) + + # If parent doesn't consume Return key, try our clickable fallback + if not consumes and keyboardEvent.event_string == "Return": + return self._tryClickableActivation(keyboardEvent) + + return consumes + + def getEnabledKeyBindings(self): + all = super().getEnabledKeyBindings() + ret = [] + for b in all: + if b.handler and self.caretNavigation.handles_navigation(b.handler): + if self.useCaretNavigationModel(None, False): + ret.append(b) + elif b.handler and b.handler.function in self.structuralNavigation.functions: + if self.useStructuralNavigationModel(False): + ret.append(b) + elif b.handler and b.handler.function in self.liveRegionManager.functions: + # This is temporary. + if self.useStructuralNavigationModel(False): + ret.append(b) + else: + ret.append(b) + return ret + + def consumesBrailleEvent(self, brailleEvent): + """Returns True if the script will consume this braille event.""" + + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = False + return super().consumesBrailleEvent(brailleEvent) + + # TODO - JD: This needs to be moved out of the scripts. + def textLines(self, obj, offset=None): + """Creates a generator that can be used to iterate document content.""" + + if not self.utilities.inDocumentContent(): + tokens = ["WEB: textLines called for non-document content", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + super().textLines(obj, offset) + return + + self._sayAllIsInterrupted = False + + sayAllStyle = _settingsManager.getSetting('sayAllStyle') + sayAllBySentence = sayAllStyle == settings.SAYALL_STYLE_SENTENCE + if offset is None: + obj, characterOffset = self.utilities.getCaretContext() + else: + characterOffset = offset + priorObj, priorOffset = self.utilities.getPriorContext() + + # TODO - JD: This is sad, but it's better than the old, broken + # clumpUtterances(). We really need to fix the speechservers' + # SayAll support. In the meantime, the generators should be + # providing one ACSS per string. + def _parseUtterances(utterances): + elements, voices = [], [] + for u in utterances: + if isinstance(u, list): + e, v = _parseUtterances(u) + elements.extend(e) + voices.extend(v) + elif isinstance(u, str): + elements.append(u) + elif isinstance(u, ACSS): + voices.append(u) + return elements, voices + + self._inSayAll = True + done = False + while not done: + if sayAllBySentence: + contents = self.utilities.getSentenceContentsAtOffset(obj, characterOffset) + else: + contents = self.utilities.getLineContentsAtOffset(obj, characterOffset) + self._sayAllContents = contents + for i, content in enumerate(contents): + obj, startOffset, endOffset, text = content + tokens = ["WEB SAY ALL CONTENT:", + i, ". ", obj, "'", text, "' (", startOffset, "-", endOffset, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if self.utilities.isInferredLabelForContents(content, contents): + continue + + if startOffset == endOffset: + continue + + if self.utilities.isLabellingInteractiveElement(obj): + continue + + if self.utilities.isLinkAncestorOfImageInContents(obj, contents): + continue + + utterances = self.speechGenerator.generateContents( + [content], eliminatePauses=True, priorObj=priorObj) + priorObj = obj + + elements, voices = _parseUtterances(utterances) + if len(elements) != len(voices): + continue + + for i, element in enumerate(elements): + context = speechserver.SayAllContext( + obj, element, startOffset, endOffset) + tokens = ["WEB", context] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._sayAllContexts.append(context) + self.eventSynthesizer.scroll_into_view(obj, startOffset, endOffset) + yield [context, voices[i]] + + lastObj, lastOffset = contents[-1][0], contents[-1][2] + obj, characterOffset = self.utilities.findNextCaretInOrder(lastObj, lastOffset - 1) + if obj == lastObj and characterOffset <= lastOffset: + obj, characterOffset = self.utilities.findNextCaretInOrder(lastObj, lastOffset) + if obj == lastObj and characterOffset <= lastOffset: + tokens = ["WEB: Cycle within object detected in textLines. Last:", + lastObj, ", ", lastOffset, "Next:", obj, ", ", characterOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + break + + done = obj is None + + self._inSayAll = False + self._sayAllContents = [] + self._sayAllContexts = [] + + msg = "WEB: textLines complete. Verifying SayAll status" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.inSayAll() + + def presentFindResults(self, obj, offset): + """Updates the context and presents the find results if appropriate.""" + + text = self.utilities.queryNonEmptyText(obj) + if not (text and text.getNSelections() > 0): + return + + document = self.utilities.getDocumentForObject(obj) + if not document: + return + + context = self.utilities.getCaretContext(documentFrame=document) + start, end = text.getSelection(0) + offset = max(offset, start) + self.utilities.setCaretContext(obj, offset, documentFrame=document) + if end - start < _settingsManager.getSetting('findResultsMinimumLength'): + return + + verbosity = _settingsManager.getSetting('findResultsVerbosity') + if verbosity == settings.FIND_SPEAK_NONE: + return + + if self._madeFindAnnouncement \ + and verbosity == settings.FIND_SPEAK_IF_LINE_CHANGED \ + and self.utilities.contextsAreOnSameLine(context, (obj, offset)): + return + + contents = self.utilities.getLineContentsAtOffset(obj, offset) + self.speakContents(contents) + self.updateBraille(obj) + + resultsCount = self.utilities.getFindResultsCount() + if resultsCount: + self.presentMessage(resultsCount) + + self._madeFindAnnouncement = True + + def sayAll(self, inputEvent, obj=None, offset=None): + """Speaks the contents of the document beginning with the present + location. Overridden in this script because the sayAll could have + been started on an object without text (such as an image). + """ + + if not self.utilities.inDocumentContent(): + tokens = ["WEB: SayAll called for non-document content", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return super().sayAll(inputEvent, obj, offset) + + obj = obj or cthulhu_state.locusOfFocus + tokens = ["WEB: SayAll called for document content", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + speech.sayAll(self.textLines(obj, offset), self.__sayAllProgressCallback) + return True + + def _rewindSayAll(self, context, minCharCount=10): + if not self.utilities.inDocumentContent(): + return super()._rewindSayAll(context, minCharCount) + + if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'): + return False + + try: + obj, start, end, string = self._sayAllContents[0] + except IndexError: + return False + + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + self.utilities.setCaretContext(obj, start) + + prevObj, prevOffset = self.utilities.findPreviousCaretInOrder(obj, start) + self.sayAll(None, prevObj, prevOffset) + return True + + def _fastForwardSayAll(self, context): + if not self.utilities.inDocumentContent(): + return super()._fastForwardSayAll(context) + + if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'): + return False + + try: + obj, start, end, string = self._sayAllContents[-1] + except IndexError: + return False + + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + self.utilities.setCaretContext(obj, end) + + nextObj, nextOffset = self.utilities.findNextCaretInOrder(obj, end) + self.sayAll(None, nextObj, nextOffset) + return True + + def __sayAllProgressCallback(self, context, progressType): + if not self.utilities.inDocumentContent(): + super().__sayAllProgressCallback(context, progressType) + return + + if progressType == speechserver.SayAllContext.INTERRUPTED: + if isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + self._sayAllIsInterrupted = True + lastKey = cthulhu_state.lastInputEvent.event_string + if lastKey == "Down" and self._fastForwardSayAll(context): + return + elif lastKey == "Up" and self._rewindSayAll(context): + return + elif not self._lastCommandWasStructNav: + cthulhu.emitRegionChanged(context.obj, context.currentOffset) + self.utilities.setCaretPosition(context.obj, context.currentOffset) + self.updateBraille(context.obj) + + self._inSayAll = False + self._sayAllContents = [] + self._sayAllContexts = [] + return + + cthulhu.setLocusOfFocus(None, context.obj, notifyScript=False) + cthulhu.emitRegionChanged( + context.obj, context.currentOffset, context.currentEndOffset, cthulhu.SAY_ALL) + self.utilities.setCaretContext(context.obj, context.currentOffset) + + def inFocusMode(self): + """ Returns True if we're in focus mode.""" + + return self._inFocusMode + + def focusModeIsSticky(self): + """Returns True if we're in 'sticky' focus mode.""" + + return self._focusModeIsSticky + + def browseModeIsSticky(self): + """Returns True if we're in 'sticky' browse mode.""" + + return self._browseModeIsSticky + + def useFocusMode(self, obj, prevObj=None): + """Returns True if we should use focus mode in obj.""" + + if self._focusModeIsSticky: + msg = "WEB: Using focus mode because focus mode is sticky" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._browseModeIsSticky: + msg = "WEB: Not using focus mode because browse mode is sticky" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.inSayAll(): + msg = "WEB: Not using focus mode because we're in SayAll." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not _settingsManager.getSetting('structNavTriggersFocusMode') \ + and self._lastCommandWasStructNav: + msg = "WEB: Not using focus mode due to struct nav settings" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if prevObj and AXObject.is_dead(prevObj): + prevObj = None + + if not _settingsManager.getSetting('caretNavTriggersFocusMode') \ + and self._lastCommandWasCaretNav \ + and not self.utilities.isNavigableToolTipDescendant(prevObj): + msg = "WEB: Not using focus mode due to caret nav settings" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not _settingsManager.getSetting('nativeNavTriggersFocusMode') \ + and not (self._lastCommandWasStructNav or self._lastCommandWasCaretNav): + msg = "WEB: Not changing focus/browse mode due to native nav settings" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return self._inFocusMode + + if self.utilities.isFocusModeWidget(obj): + tokens = ["WEB: Using focus mode because", obj, "is a focus mode widget"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + doNotToggle = AXUtilities.is_link(obj) or AXUtilities.is_radio_button(obj) + if self._inFocusMode and doNotToggle and self.utilities.lastInputEventWasUnmodifiedArrow(): + tokens = ["WEB: Staying in focus mode due to arrowing in role of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self._inFocusMode and self.utilities.isWebAppDescendant(obj): + if self.utilities.forceBrowseModeForWebAppDescendant(obj): + tokens = ["WEB: Forcing browse mode for web app descendant", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + msg = "WEB: Staying in focus mode because we're inside a web application" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + tokens = ["WEB: Not using focus mode for", obj, "due to lack of cause"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + def speakContents(self, contents, **args): + """Speaks the specified contents.""" + + utterances = self.speechGenerator.generateContents(contents, **args) + speech.speak(utterances) + + def sayCharacter(self, obj): + """Speaks the character at the current caret position.""" + + if not self._lastCommandWasCaretNav \ + and not self.utilities.isContentEditableWithEmbeddedObjects(obj): + super().sayCharacter(obj) + return + + document = self.utilities.getTopLevelDocumentForObject(obj) + obj, offset = self.utilities.getCaretContext(documentFrame=document) + if not obj: + return + + contents = None + if self.utilities.treatAsEndOfLine(obj, offset) and AXObject.supports_text(obj): + char = obj.queryText().getText(offset, offset + 1) + if char == self.EMBEDDED_OBJECT_CHARACTER: + char = "" + contents = [[obj, offset, offset + 1, char]] + else: + contents = self.utilities.getCharacterContentsAtOffset(obj, offset) + + if not contents: + return + + obj, start, end, string = contents[0] + if start > 0: + string = string or "\n" + + if string: + self.speakMisspelledIndicator(obj, start) + self.speakCharacter(string) + else: + self.speakContents(contents) + + self.pointOfReference["lastTextUnitSpoken"] = "char" + + def sayWord(self, obj): + """Speaks the word at the current caret position.""" + + isEditable = self.utilities.isContentEditableWithEmbeddedObjects(obj) + if not self._lastCommandWasCaretNav and not isEditable: + super().sayWord(obj) + return + + document = self.utilities.getTopLevelDocumentForObject(obj) + obj, offset = self.utilities.getCaretContext(documentFrame=document) + keyString, mods = self.utilities.lastKeyAndModifiers() + if keyString == "Right": + offset -= 1 + + wordContents = self.utilities.getWordContentsAtOffset(obj, offset, useCache=True) + textObj, startOffset, endOffset, word = wordContents[0] + self.speakMisspelledIndicator(textObj, startOffset) + self.speakContents(wordContents) + self.pointOfReference["lastTextUnitSpoken"] = "word" + + def sayLine(self, obj): + """Speaks the line at the current caret position.""" + + isEditable = self.utilities.isContentEditableWithEmbeddedObjects(obj) + if not (self._lastCommandWasCaretNav or self._lastCommandWasStructNav) and not isEditable: + super().sayLine(obj) + return + + document = self.utilities.getTopLevelDocumentForObject(obj) + priorObj = None + if self._lastCommandWasCaretNav or isEditable: + priorObj, priorOffset = self.utilities.getPriorContext(documentFrame=document) + + obj, offset = self.utilities.getCaretContext(documentFrame=document) + contents = self.utilities.getLineContentsAtOffset(obj, offset, useCache=True) + self.speakContents(contents, priorObj=priorObj) + self.pointOfReference["lastTextUnitSpoken"] = "line" + + def presentObject(self, obj, **args): + if not self.utilities.inDocumentContent(obj) or AXUtilities.is_document(obj): + super().presentObject(obj, **args) + return + + if AXUtilities.is_status_bar(obj): + super().presentObject(obj, **args) + return + + priorObj = args.get("priorObj") + if self._lastCommandWasCaretNav or args.get("includeContext") \ + or self.utilities.getTable(obj): + priorObj, priorOffset = self.utilities.getPriorContext() + args["priorObj"] = priorObj + + if AXUtilities.is_entry(obj): + super().presentObject(obj, **args) + return + + interrupt = args.get("interrupt", False) + tokens = ["WEB: Presenting object", obj, ". Interrupt:", interrupt] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # We shouldn't use cache in this method, because if the last thing we presented + # included this object and offset (e.g. a Say All or Mouse Review), we're in + # danger of presented irrelevant context. + useCache = False + offset = args.get("offset", 0) + contents = self.utilities.getObjectContentsAtOffset(obj, offset, useCache) + self.displayContents(contents) + self.speakContents(contents, **args) + + def updateBrailleForNewCaretPosition(self, obj): + """Try to reposition the cursor without having to do a full update.""" + + text = self.utilities.queryNonEmptyText(obj) + if text and self.EMBEDDED_OBJECT_CHARACTER in text.getText(0, -1): + self.updateBraille(obj) + return + + super().updateBrailleForNewCaretPosition(obj) + + def updateBraille(self, obj, **args): + """Updates the braille display to show the given object.""" + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: disabled", True) + return + + if self._inFocusMode: + tokens = ["WEB: updating braille in focus mode", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + super().updateBraille(obj, **args) + return + + document = args.get("documentFrame", self.utilities.getTopLevelDocumentForObject(obj)) + if not document: + tokens = ["WEB: updating braille for non-document object", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + super().updateBraille(obj, **args) + return + + isContentEditable = self.utilities.isContentEditableWithEmbeddedObjects(obj) + + if not self._lastCommandWasCaretNav \ + and not self._lastCommandWasStructNav \ + and not isContentEditable \ + and not self.utilities.isPlainText() \ + and not self.utilities.lastInputEventWasCaretNavWithSelection(): + tokens = ["WEB: updating braille for unhandled navigation type", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + super().updateBraille(obj, **args) + return + + obj, offset = self.utilities.getCaretContext( + documentFrame=document, getZombieReplicant=True) + if offset > 0 and isContentEditable: + text = self.utilities.queryNonEmptyText(obj) + if text: + offset = min(offset, text.characterCount) + + contents = self.utilities.getLineContentsAtOffset(obj, offset) + self.displayContents(contents, documentFrame=document) + + def displayContents(self, contents, **args): + """Displays contents in braille.""" + + if not _settingsManager.getSetting('enableBraille') \ + and not _settingsManager.getSetting('enableBrailleMonitor'): + debug.printMessage(debug.LEVEL_INFO, "BRAILLE: disabled", True) + return + + line = self.getNewBrailleLine(clearBraille=True, addLine=True) + document = args.get("documentFrame") + contents = self.brailleGenerator.generateContents(contents, documentFrame=document) + if not contents: + return + + regions, focusedRegion = contents + for region in regions: + self.addBrailleRegionsToLine(region, line) + + if line.regions: + line.regions[-1].string = line.regions[-1].string.rstrip(" ") + + self.setBrailleFocus(focusedRegion, getLinkMask=False) + self.refreshBraille(panToCursor=True, getLinkMask=False) + + def panBrailleLeft(self, inputEvent=None, panAmount=0): + """Pans braille to the left.""" + + if self.flatReviewPresenter.is_active() \ + or not self.utilities.inDocumentContent() \ + or not self.isBrailleBeginningShowing(): + super().panBrailleLeft(inputEvent, panAmount) + return + + contents = self.utilities.getPreviousLineContents() + if not contents: + return + + obj, start, end, string = contents[0] + self.utilities.setCaretPosition(obj, start) + self.updateBraille(obj) + + # Hack: When panning to the left in a document, we want to start at + # the right/bottom of each new object. For now, we'll pan there. + # When time permits, we'll give our braille code some smarts. + while self.panBrailleInDirection(panToLeft=False): + pass + + self.refreshBraille(False) + return True + + def panBrailleRight(self, inputEvent=None, panAmount=0): + """Pans braille to the right.""" + + if self.flatReviewPresenter.is_active() \ + or not self.utilities.inDocumentContent() \ + or not self.isBrailleEndShowing(): + super().panBrailleRight(inputEvent, panAmount) + return + + contents = self.utilities.getNextLineContents() + if not contents: + return + + obj, start, end, string = contents[0] + self.utilities.setCaretPosition(obj, start) + self.updateBraille(obj) + + # Hack: When panning to the right in a document, we want to start at + # the left/top of each new object. For now, we'll pan there. When time + # permits, we'll give our braille code some smarts. + while self.panBrailleInDirection(panToLeft=True): + pass + + self.refreshBraille(False) + return True + + def useCaretNavigationModel(self, keyboardEvent, debugOutput=True): + """Returns True if caret navigation should be used.""" + + if not _settingsManager.getSetting('caretNavigationEnabled'): + if debugOutput: + msg = "WEB: Not using caret navigation: it's not enabled." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._inFocusMode: + if debugOutput: + msg = "WEB: Not using caret navigation: focus mode is active." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not self.utilities.inDocumentContent(): + if debugOutput: + tokens = ["WEB: Not using caret navigation: locusOfFocus", + cthulhu_state.locusOfFocus, "is not in document content."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if keyboardEvent and keyboardEvent.modifiers & keybindings.SHIFT_MODIFIER_MASK: + if debugOutput: + msg = "WEB: Not using caret navigation: shift was used." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if debugOutput: + tokens = ["WEB: Using caret navigation: in browse mode and locusOfFocus", + cthulhu_state.locusOfFocus, "is in document content."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def useStructuralNavigationModel(self, debugOutput=True): + """Returns True if structural navigation should be used.""" + + if not self.structuralNavigation.enabled: + if debugOutput: + msg = "WEB: Not using structural navigation: it's not enabled." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._inFocusMode: + if debugOutput: + msg = "WEB: Not using structural navigation: focus mode is active." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not self.utilities.inDocumentContent(): + if debugOutput: + tokens = ["WEB: Not using structural navigation: locusOfFocus", + cthulhu_state.locusOfFocus, "is not in document content."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if debugOutput: + tokens = ["WEB: Using structural navigation: in browse mode and locusOfFocus", + cthulhu_state.locusOfFocus, "is in document content."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None): + """To-be-removed. Returns the string, caretOffset, startOffset.""" + + if self._inFocusMode or not self.utilities.inDocumentContent(obj) \ + or self.utilities.isFocusModeWidget(obj): + return super().getTextLineAtCaret(obj, offset, startOffset, endOffset) + + text = self.utilities.queryNonEmptyText(obj) + if offset is None: + try: + offset = max(0, text.caretOffset) + except Exception: + offset = 0 + + if text and startOffset is not None and endOffset is not None: + return text.getText(startOffset, endOffset), offset, startOffset + + contextObj, contextOffset = self.utilities.getCaretContext(documentFrame=None) + if contextObj == obj: + caretOffset = contextOffset + else: + caretOffset = offset + + contents = self.utilities.getLineContentsAtOffset(obj, offset) + contents = list(filter(lambda x: x[0] == obj, contents)) + if len(contents) == 1: + index = 0 + else: + index = self.utilities.findObjectInContents(obj, offset, contents) + + if index > -1: + candidate, startOffset, endOffset, string = contents[index] + if self.EMBEDDED_OBJECT_CHARACTER not in string: + return string, caretOffset, startOffset + + return "", 0, 0 + + def moveToMouseOver(self, inputEvent): + """Moves the context to/from the mouseover which has just appeared.""" + + if not self._lastMouseOverObject: + self.presentMessage(messages.MOUSE_OVER_NOT_FOUND) + return + + if self._inMouseOverObject: + x, y = self.oldMouseCoordinates + self.eventSynthesizer.route_to_point(x, y) + self.restorePreMouseOverContext() + return + + obj = self._lastMouseOverObject + obj, offset = self.utilities.findFirstCaretContext(obj, 0) + if not obj: + return + + if AXUtilities.is_focusable(obj): + obj.queryComponent().grabFocus() + + contents = self.utilities.getObjectContentsAtOffset(obj, offset) + self.utilities.setCaretPosition(obj, offset) + self.speakContents(contents) + self.updateBraille(obj) + self._inMouseOverObject = True + + def restorePreMouseOverContext(self): + """Cleans things up after a mouse-over object has been hidden.""" + + obj, offset = self._preMouseOverContext + self.utilities.setCaretPosition(obj, offset) + self.speakContents(self.utilities.getObjectContentsAtOffset(obj, offset)) + self.updateBraille(obj) + self._inMouseOverObject = False + self._lastMouseOverObject = None + + def enableStickyBrowseMode(self, inputEvent, forceMessage=False): + if not self._browseModeIsSticky or forceMessage: + self.presentMessage(messages.MODE_BROWSE_IS_STICKY) + + self._inFocusMode = False + self._focusModeIsSticky = False + self._browseModeIsSticky = True + self.refreshKeyGrabs() + + def enableStickyFocusMode(self, inputEvent, forceMessage=False): + if not self._focusModeIsSticky or forceMessage: + self.presentMessage(messages.MODE_FOCUS_IS_STICKY) + + self._inFocusMode = True + self._focusModeIsSticky = True + self._browseModeIsSticky = False + self.refreshKeyGrabs() + + def toggleLayoutMode(self, inputEvent): + layoutMode = not _settingsManager.getSetting('layoutMode') + if layoutMode: + self.presentMessage(messages.MODE_LAYOUT) + else: + self.presentMessage(messages.MODE_OBJECT) + _settingsManager.setSetting('layoutMode', layoutMode) + + def togglePresentationMode(self, inputEvent, documentFrame=None): + [obj, characterOffset] = self.utilities.getCaretContext(documentFrame) + if self._inFocusMode: + parent = AXObject.get_parent(obj) + if AXUtilities.is_list_box(parent): + self.utilities.setCaretContext(parent, -1) + elif AXUtilities.is_menu(parent): + self.utilities.setCaretContext(AXObject.get_parent(parent), -1) + if not self._loadingDocumentContent: + self.presentMessage(messages.MODE_BROWSE) + else: + if not self.utilities.grabFocusWhenSettingCaret(obj) \ + and (self._lastCommandWasCaretNav \ + or self._lastCommandWasStructNav \ + or inputEvent): + self.utilities.grabFocus(obj) + + self.presentMessage(messages.MODE_FOCUS) + self._inFocusMode = not self._inFocusMode + self._focusModeIsSticky = False + self._browseModeIsSticky = False + self.refreshKeyGrabs() + + def _tryClickableActivation(self, keyboardEvent): + """Try to activate clickable element - returns True if we should consume the event.""" + + obj = cthulhu_state.locusOfFocus + if not obj or not self.utilities.inDocumentContent(obj): + return False + + # Skip form controls where Return should have normal behavior + from cthulhu import ax_utilities + if (ax_utilities.AXUtilities.is_entry(obj) or + ax_utilities.AXUtilities.is_text(obj) or + ax_utilities.AXUtilities.is_password_text(obj) or + ax_utilities.AXUtilities.is_combo_box(obj) or + ax_utilities.AXUtilities.is_button(obj) or + ax_utilities.AXUtilities.is_push_button(obj) or + ax_utilities.AXUtilities.is_link(obj)): + return False + + # Try clickable activation for non-standard clickable elements + # Store focus information before clicking for potential restoration + original_focus = obj + + # First try the standard clickable detection + if self.utilities.isClickableElement(obj): + from cthulhu import ax_event_synthesizer + # Give immediate feedback that activation is starting + self.presentMessage("Activating...") + result = ax_event_synthesizer.AXEventSynthesizer.click_object(obj) + if result: + # Schedule success message after a brief delay + self._presentDelayedMessage("Element activated", 50) + # Try to restore focus to the clicked element after a brief delay + self._restoreFocusAfterClick(original_focus) + return True + + # If that didn't work, try a more permissive approach for any element with click action + from cthulhu import ax_object + if ax_object.AXObject.has_action(obj, "click"): + from cthulhu import ax_event_synthesizer + # Give immediate feedback that activation is starting + self.presentMessage("Activating...") + result = ax_event_synthesizer.AXEventSynthesizer.click_object(obj) + if result: + # Schedule success message after a brief delay + self._presentDelayedMessage("Element activated", 50) + # Try to restore focus to the clicked element after a brief delay + self._restoreFocusAfterClick(original_focus) + return True + + return False + + def _restoreFocusAfterClick(self, original_focus): + """Try to restore focus after a click action that may have caused DOM changes.""" + try: + from gi.repository import GObject + from cthulhu import ax_object + + # Store the document and caret position to restore navigation context + document = None + caret_offset = -1 + try: + # Find the document root + obj = original_focus + while obj and not ax_object.AXObject.is_dead(obj): + if self.utilities.isDocument(obj): + document = obj + break + parent = ax_object.AXObject.get_parent(obj) + if parent == obj: # Avoid infinite loops + break + obj = parent + + # Get current caret position if available + if document: + try: + caret_offset = ax_object.AXObject.get_caret_offset(document) + except Exception: + pass + + except Exception: + pass + + def restore_focus(): + try: + # First try direct focus restoration if object still exists + if not ax_object.AXObject.is_dead(original_focus): + original_focus.grabFocus() + return False + + # If we have document and caret info, try to restore position + if document and not ax_object.AXObject.is_dead(document) and caret_offset >= 0: + try: + # Set caret back to where it was + ax_object.AXObject.set_caret_offset(document, caret_offset) + # Focus the document to make sure screen reader tracks properly + document.grabFocus() + return False + except Exception: + pass + + # Last resort: try to focus the document if we have it + if document and not ax_object.AXObject.is_dead(document): + document.grabFocus() + + except Exception: + pass # Focus restoration is best effort + return False # Don't repeat the timeout + + # Delay restoration to allow JavaScript and DOM changes to complete + GObject.timeout_add(150, restore_focus) # 150ms delay for DOM changes + + except Exception: + pass # Focus restoration is best effort + + def _presentDelayedMessage(self, message, delay_ms): + """Present a message after a specified delay in milliseconds.""" + try: + from gi.repository import GObject + + def present_message(): + self.presentMessage(message) + return False # Don't repeat + + GObject.timeout_add(delay_ms, present_message) + except Exception: + # If delay fails, present immediately + self.presentMessage(message) + + def activateClickableElement(self, inputEvent): + """Activates clickable element at current focus via Return key.""" + return self._tryClickableActivation(inputEvent) + + def locusOfFocusChanged(self, event, oldFocus, newFocus): + """Handles changes of focus of interest to the script.""" + + if newFocus and self.utilities.isZombie(newFocus): + tokens = ["WEB: New focus is Zombie:", newFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if newFocus and AXObject.is_dead(newFocus): + msg = "WEB: New focus is dead" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + document = self.utilities.getTopLevelDocumentForObject(newFocus) + if not document and self.utilities.isDocument(newFocus): + document = newFocus + + if not document: + msg = "WEB: Locus of focus changed to non-document obj" + self._madeFindAnnouncement = False + self._inFocusMode = False + msg = "locus of focus no longer in document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.refreshKeyGrabs() + return False + + if self.flatReviewPresenter.is_active(): + self.flatReviewPresenter.quit() + + caretOffset = 0 + if self.utilities.inFindContainer(oldFocus) \ + or (self.utilities.isDocument(newFocus) and oldFocus == cthulhu_state.activeWindow): + contextObj, contextOffset = self.utilities.getCaretContext(documentFrame=document) + if contextObj and not self.utilities.isZombie(contextObj): + newFocus, caretOffset = contextObj, contextOffset + + if AXUtilities.is_unknown_or_redundant(newFocus): + msg = "WEB: Event source has bogus role. Likely browser bug." + debug.printMessage(debug.LEVEL_INFO, msg, True) + newFocus, offset = self.utilities.findFirstCaretContext(newFocus, 0) + + text = self.utilities.queryNonEmptyText(newFocus) + if text and (0 <= text.caretOffset <= text.characterCount): + caretOffset = text.caretOffset + + self.utilities.setCaretContext(newFocus, caretOffset, document) + self.updateBraille(newFocus, documentFrame=document) + cthulhu.emitRegionChanged(newFocus, caretOffset) + + contents = None + args = {} + if self._lastCommandWasMouseButton and event \ + and event.type.startswith("object:text-caret-moved"): + msg = "WEB: Last input event was mouse button. Generating line." + debug.printMessage(debug.LEVEL_INFO, msg, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset) + args['priorObj'] = oldFocus + elif self.utilities.isContentEditableWithEmbeddedObjects(newFocus) \ + and (self._lastCommandWasCaretNav or self._lastCommandWasStructNav) \ + and not (AXUtilities.is_table_cell(newFocus) and AXObject.get_name(newFocus)): + tokens = ["WEB: New focus", newFocus, "content editable. Generating line."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset) + elif self.utilities.isAnchor(newFocus): + tokens = ["WEB: New focus", newFocus, "is anchor. Generating line."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, 0) + elif self.utilities.lastInputEventWasPageNav() \ + and not self.utilities.getTable(newFocus) \ + and not self.utilities.isFeedArticle(newFocus): + tokens = ["WEB: New focus", newFocus, "was scrolled to. Generating line."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset) + elif self.utilities.isFocusedWithMathChild(newFocus): + tokens = ["WEB: New focus", newFocus, "has math child. Generating line."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset) + elif AXUtilities.is_heading(newFocus): + tokens = ["WEB: New focus", newFocus, "is heading. Generating object."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.utilities.getObjectContentsAtOffset(newFocus, 0) + elif self.utilities.caretMovedToSamePageFragment(event, oldFocus): + tokens = ["WEB: Source", event.source, "is same page fragment. Generating line."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, 0) + elif event and event.type.startswith("object:children-changed:remove") \ + and self.utilities.isFocusModeWidget(newFocus): + tokens = ["WEB: New focus", newFocus, + "is recovery from removed child. Generating speech."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + elif self.utilities.lastInputEventWasLineNav() and self.utilities.isZombie(oldFocus): + msg = "WEB: Last input event was line nav; oldFocus is zombie. Generating line." + debug.printMessage(debug.LEVEL_INFO, msg, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset) + elif self.utilities.lastInputEventWasLineNav() and event \ + and event.type.startswith("object:children-changed"): + msg = "WEB: Last input event was line nav and children changed. Generating line." + debug.printMessage(debug.LEVEL_INFO, msg, True) + contents = self.utilities.getLineContentsAtOffset(newFocus, caretOffset) + else: + tokens = ["WEB: New focus", newFocus, "is not a special case. Generating speech."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + args['priorObj'] = oldFocus + + if newFocus and AXObject.is_dead(newFocus): + msg = "WEB: New focus has since died" + debug.printMessage(debug.LEVEL_INFO, msg, True) + if self._getQueuedEvent("object:state-changed:focused", True): + msg = "WEB: Have matching focused event. Not speaking contents" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if contents: + self.speakContents(contents, **args) + else: + utterances = self.speechGenerator.generateSpeech(newFocus, **args) + speech.speak(utterances) + + self._saveFocusedObjectInfo(newFocus) + + if self.utilities.inTopLevelWebApp(newFocus) and not self._browseModeIsSticky: + announce = not self.utilities.inDocumentContent(oldFocus) + self.enableStickyFocusMode(None, announce) + return True + + if not self._focusModeIsSticky \ + and not self._browseModeIsSticky \ + and self.useFocusMode(newFocus, oldFocus) != self._inFocusMode: + self.togglePresentationMode(None, document) + + if not self.utilities.inDocumentContent(oldFocus): + self.refreshKeyGrabs() + + return True + + def onActiveChanged(self, event): + """Callback for object:state-changed:active accessibility events.""" + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not event.detail1: + msg = "WEB: Ignoring because event source is now inactive" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXUtilities.is_dialog_or_alert(event.source): + msg = "WEB: Event handled: Setting locusOfFocus to event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source) + return True + + return False + + def onActiveDescendantChanged(self, event): + """Callback for object:active-descendant-changed accessibility events.""" + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + return True + + def onBusyChanged(self, event): + """Callback for object:state-changed:busy accessibility events.""" + + if event.detail1 and self._loadingDocumentContent: + msg = "WEB: Ignoring: Already loading document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not AXUtilities.is_document_web(event.source) \ + and not self.utilities.isOrDescendsFrom(cthulhu_state.locusOfFocus, event.source): + msg = "WEB: Ignoring: Not document and not something we're in" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + self.structuralNavigation.clearCache() + + if self.utilities.getDocumentForObject(AXObject.get_parent(event.source)): + msg = "WEB: Ignoring: Event source is nested document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + obj, offset = self.utilities.getCaretContext() + if not obj or self.utilities.isZombie(obj): + self.utilities.clearCaretContext() + + shouldPresent = True + if not (AXUtilities.is_showing(event.source) or AXUtilities.is_visible(event.source)): + shouldPresent = False + msg = "WEB: Not presenting because source is not showing or visible" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif not self.utilities.documentFrameURI(event.source): + shouldPresent = False + msg = "WEB: Not presenting because source lacks URI" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif not event.detail1 and self._inFocusMode and not self.utilities.isZombie(obj): + shouldPresent = False + tokens = ["WEB: Not presenting due to focus mode for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not _settingsManager.getSetting('onlySpeakDisplayedText') and shouldPresent: + if event.detail1: + self.presentMessage(messages.PAGE_LOADING_START) + elif AXObject.get_name(event.source): + msg = messages.PAGE_LOADING_END_NAMED % AXObject.get_name(event.source) + self.presentMessage(msg, resetStyles=False) + else: + self.presentMessage(messages.PAGE_LOADING_END) + + activeDocument = self.utilities.activeDocument() + if activeDocument and activeDocument != event.source: + msg = "WEB: Ignoring: Event source is not active document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + self._loadingDocumentContent = event.detail1 + if event.detail1: + return True + + self.utilities.clearCachedObjects() + if AXObject.is_dead(obj): + obj = None + + if not AXObject.is_dead(cthulhu_state.locusOfFocus) \ + and not self.utilities.inDocumentContent(cthulhu_state.locusOfFocus) \ + and AXUtilities.is_focused(cthulhu_state.locusOfFocus): + msg = "WEB: Not presenting content, focus is outside of document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if _settingsManager.getSetting('pageSummaryOnLoad') and shouldPresent: + obj = obj or event.source + tokens = ["WEB: Getting page summary for obj", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + summary = self.utilities.getPageSummary(obj) + if summary: + self.presentMessage(summary) + + obj, offset = self.utilities.getCaretContext() + if not AXUtilities.is_busy(event.source) \ + and self.utilities.isTopLevelWebApp(event.source): + tokens = ["WEB: Setting locusOfFocus to", obj, "with sticky focus mode"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj) + self.enableStickyFocusMode(None, True) + return True + + if self.useFocusMode(obj) != self._inFocusMode: + self.togglePresentationMode(None) + + if not obj: + msg = "WEB: Could not get caret context" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isFocusModeWidget(obj): + tokens = ["WEB: Setting locus of focus to focusModeWidget", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj) + return True + + if self.utilities.isLink(obj) and AXUtilities.is_focused(obj): + tokens = ["WEB: Setting locus of focus to focused link", obj, ". No SayAll."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj) + return True + + if offset > 0: + tokens = ["WEB: Setting locus of focus to context obj", obj, ". No SayAll"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj) + return True + + if not AXUtilities.is_focused(cthulhu_state.locusOfFocus): + tokens = ["WEB: Setting locus of focus to context obj", obj, "(no notification)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj, False) + + self.updateBraille(obj) + if self.utilities.documentFragment(event.source): + msg = "WEB: Not doing SayAll due to page fragment" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif not _settingsManager.getSetting('sayAllOnLoad'): + msg = "WEB: Not doing SayAll due to sayAllOnLoad being False" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.speakContents(self.utilities.getLineContentsAtOffset(obj, offset)) + elif _settingsManager.getSetting('enableSpeech'): + msg = "WEB: Doing SayAll" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.sayAll(None) + else: + msg = "WEB: Not doing SayAll due to enableSpeech being False" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + return True + + def onCaretMoved(self, event): + """Callback for object:text-caret-moved accessibility events.""" + + self.utilities.sanityCheckActiveWindow() + + if self.utilities.isZombie(event.source): + msg = "WEB: Event source is Zombie" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + document = self.utilities.getTopLevelDocumentForObject(event.source) + if not document: + if self.utilities.eventIsBrowserUINoise(event): + msg = "WEB: Ignoring event believed to be browser UI noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsBrowserUIAutocompleteNoise(event): + msg = "WEB: Ignoring event believed to be browser UI autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + obj, offset = self.utilities.getCaretContext(document, False, False) + tokens = ["WEB: Context: ", obj, ", ", offset, "(focus: ", cthulhu_state.locusOfFocus, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if self._lastCommandWasCaretNav: + msg = "WEB: Event ignored: Last command was caret nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._lastCommandWasStructNav: + msg = "WEB: Event ignored: Last command was struct nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._lastCommandWasMouseButton: + msg = "WEB: Last command was mouse button" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if (event.source, event.detail1) == (obj, offset): + msg = "WEB: Event is for current caret context." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if (event.source, event.detail1) == self._lastMouseButtonContext: + msg = "WEB: Event is for last mouse button context." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + self._lastMouseButtonContext = event.source, event.detail1 + + msg = "WEB: Event handled: Last command was mouse button" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.setCaretContext(event.source, event.detail1) + notify = not self.utilities.isEntryDescendant(event.source) + cthulhu.setLocusOfFocus(event, event.source, notify, True) + if cthulhu_state.locusOfFocus == event.source: + self.updateBraille(event.source) + return True + + if self.utilities.lastInputEventWasTab(): + msg = "WEB: Last input event was Tab." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if self.utilities.isDocument(event.source): + msg = "WEB: Event ignored: Caret moved in document due to Tab." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.inFindContainer(): + msg = "WEB: Event handled: Presenting find results" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.presentFindResults(event.source, event.detail1) + self._saveFocusedObjectInfo(cthulhu_state.locusOfFocus) + return True + + if not self.utilities.eventIsFromLocusOfFocusDocument(event): + msg = "WEB: Event ignored: Not from locus of focus document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.textEventIsDueToInsertion(event): + msg = "WEB: Event handled: Updating position due to insertion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._saveLastCursorPosition(event.source, event.detail1) + return True + + if self.utilities.textEventIsDueToDeletion(event): + msg = "WEB: Event handled: Updating position due to deletion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._saveLastCursorPosition(event.source, event.detail1) + return True + + if self.utilities.isItemForEditableComboBox(cthulhu_state.locusOfFocus, event.source) \ + and not self.utilities.lastInputEventWasCharNav() \ + and not self.utilities.lastInputEventWasLineBoundaryNav(): + msg = "WEB: Event ignored: Editable combobox noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsAutocompleteNoise(event, document): + msg = "WEB: Event ignored: Autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._inFocusMode and self.utilities.caretMovedOutsideActiveGrid(event): + msg = "WEB: Event ignored: Caret moved outside active grid during focus mode" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.treatEventAsSpinnerValueChange(event): + msg = "WEB: Event handled as the value-change event we wish we'd get" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.updateBraille(event.source) + self._presentTextAtNewCaretPosition(event) + return True + + if not self.utilities.queryNonEmptyText(event.source) \ + and not AXUtilities.is_editable(event.source): + msg = "WEB: Event ignored: Was for non-editable object we're treating as textless" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + obj, offset = self.utilities.findFirstCaretContext(event.source, event.detail1) + notify = force = handled = False + AXObject.clear_cache(event.source) + + if self.utilities.lastInputEventWasPageNav(): + msg = "WEB: Caret moved due to scrolling." + debug.printMessage(debug.LEVEL_INFO, msg, True) + notify = force = handled = True + + elif self.utilities.caretMovedToSamePageFragment(event): + msg = "WEB: Caret moved to fragment." + debug.printMessage(debug.LEVEL_INFO, msg, True) + notify = force = handled = True + + elif self.utilities.lastInputEventWasCaretNav(): + msg = "WEB: Caret moved due to native caret navigation." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + elif self.utilities.isTextField(event.source) \ + and AXUtilities.is_focused(event.source) \ + and event.source != cthulhu_state.locusOfFocus: + msg = "WEB: Focused text field is not (yet) the locus of focus." + debug.printMessage(debug.LEVEL_INFO, msg, True) + notify = force = handled = True + + tokens = ["WEB: Setting context and focus to: ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.setCaretContext(obj, offset, document) + cthulhu.setLocusOfFocus(event, obj, notify, force) + return handled + + def onCheckedChanged(self, event): + """Callback for object:state-changed:checked accessibility events.""" + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + obj, offset = self.utilities.getCaretContext() + if obj != event.source: + msg = "WEB: Event source is not context object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + oldObj, oldState = self.pointOfReference.get('checkedChange', (None, 0)) + if hash(oldObj) == hash(obj) and oldState == event.detail1: + msg = "WEB: Ignoring event, state hasn't changed" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not (self._lastCommandWasCaretNav and AXUtilities.is_radio_button(obj)): + msg = "WEB: Event is something default can handle" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + self.presentObject(obj, alreadyFocused=True, interrupt=True) + self.pointOfReference['checkedChange'] = hash(obj), event.detail1 + return True + + def onChildrenAdded(self, event): + """Callback for object:children-changed:add accessibility events.""" + + AXObject.clear_cache_now("children-changed event.") + if self.utilities.eventIsBrowserUINoise(event): + msg = "WEB: Ignoring event believed to be browser UI noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + isLiveRegion = self.utilities.isLiveRegion(event.source) + document = self.utilities.getTopLevelDocumentForObject(event.source) + if document and not isLiveRegion: + if event.source == cthulhu_state.locusOfFocus: + tokens = ["WEB: Dumping cache and context: source is focus", + cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.dumpCache(document, preserveContext=False) + elif AXObject.is_dead(cthulhu_state.locusOfFocus): + msg = "WEB: Dumping cache: dead focus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.dumpCache(document, preserveContext=True) + elif AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.source): + tokens = ["WEB: Dumping cache: source is ancestor of focus", + cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.dumpCache(document, preserveContext=True) + else: + tokens = ["WEB: Not dumping full cache. Focus is", cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.clearCachedObjects() + + elif isLiveRegion: + if self.utilities.handleAsLiveRegion(event): + msg = "WEB: Event to be handled as live region" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.liveRegionManager.handleEvent(event) + else: + msg = "WEB: Ignoring because live region event not to be handled." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + else: + msg = "WEB: Could not get document for event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._loadingDocumentContent: + msg = "WEB: Ignoring because document content is being loaded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isZombie(document): + tokens = ["WEB: Ignoring because", document, "is zombified."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if AXUtilities.is_busy(document): + tokens = ["WEB: Ignoring because", document, "is busy."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if not event.any_data or self.utilities.isZombie(event.any_data): + msg = "WEB: Ignoring because any data is null or zombified." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.handleEventFromContextReplicant(event, event.any_data): + msg = "WEB: Event handled by updating locusOfFocus and context to child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXUtilities.is_alert(event.any_data): + if event.any_data == self.utilities.lastQueuedLiveRegion(): + tokens = ["WEB: Ignoring", event.any_data, "(is last queued live region)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + msg = "WEB: Presenting event.any_data" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.presentObject(event.any_data, interrupt=True) + + focused = AXUtilities.get_focused_object(event.any_data) + if focused: + notify = self.utilities.queryNonEmptyText(focused) is None + tokens = ["WEB: Setting locusOfFocus and caret context to", focused] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, focused, notify) + self.utilities.setCaretContext(focused, 0) + return True + + if self.lastMouseRoutingTime and 0 < time.time() - self.lastMouseRoutingTime < 1: + utterances = [] + utterances.append(messages.NEW_ITEM_ADDED) + utterances.extend(self.speechGenerator.generateSpeech(event.any_data, force=True)) + speech.speak(utterances) + self._lastMouseOverObject = event.any_data + self.preMouseOverContext = self.utilities.getCaretContext() + return True + + return False + + def onChildrenRemoved(self, event): + """Callback for object:children-changed:removed accessibility events.""" + + AXObject.clear_cache_now("children-changed event.") + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._loadingDocumentContent: + msg = "WEB: Ignoring because document content is being loaded." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isLiveRegion(event.source): + if self.utilities.handleEventForRemovedChild(event): + msg = "WEB: Event handled for removed live-region child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + msg = "WEB: Ignoring removal from live region." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + document = self.utilities.getTopLevelDocumentForObject(event.source) + if document: + if event.source == cthulhu_state.locusOfFocus: + tokens = ["WEB: Dumping cache and context: source is focus", + cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.dumpCache(document, preserveContext=False) + elif AXObject.is_dead(cthulhu_state.locusOfFocus): + msg = "WEB: Dumping cache: dead focus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.dumpCache(document, preserveContext=True) + elif AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.source): + tokens = ["WEB: Dumping cache: source is ancestor of focus", + cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.dumpCache(document, preserveContext=True) + else: + tokens = ["WEB: Not dumping full cache. Focus is", cthulhu_state.locusOfFocus] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.clearCachedObjects() + + if self.utilities.handleEventForRemovedChild(event): + msg = "WEB: Event handled for removed child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onColumnReordered(self, event): + """Callback for object:column-reordered accessibility events.""" + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if event.source != self.utilities.getTable(cthulhu_state.locusOfFocus): + tokens = ["WEB: locusOfFocus (", cthulhu_state.locusOfFocus, ") is not in this table"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + self.pointOfReference['last-table-sort-time'] = time.time() + self.presentMessage(messages.TABLE_REORDERED_COLUMNS) + header = self.utilities.containingTableHeader(cthulhu_state.locusOfFocus) + if header: + self.presentMessage(self.utilities.getSortOrderDescription(header, True)) + + return True + + def onDocumentLoadComplete(self, event): + """Callback for document:load-complete accessibility events.""" + + if self.utilities.getDocumentForObject(AXObject.get_parent(event.source)): + msg = "WEB: Ignoring: Event source is nested document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "WEB: Updating loading state and resetting live regions" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._loadingDocumentContent = False + self.liveRegionManager.reset() + return True + + def onDocumentLoadStopped(self, event): + """Callback for document:load-stopped accessibility events.""" + + if self.utilities.getDocumentForObject(AXObject.get_parent(event.source)): + msg = "WEB: Ignoring: Event source is nested document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "WEB: Updating loading state" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._loadingDocumentContent = False + return True + + def onDocumentReload(self, event): + """Callback for document:reload accessibility events.""" + + if self.utilities.getDocumentForObject(AXObject.get_parent(event.source)): + msg = "WEB: Ignoring: Event source is nested document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "WEB: Updating loading state" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._loadingDocumentContent = True + return True + + def onExpandedChanged(self, event): + """Callback for object:state-changed:expanded accessibility events.""" + + if self.utilities.isZombie(event.source): + msg = "WEB: Event source is Zombie" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + obj, offset = self.utilities.getCaretContext(searchIfNeeded=False) + tokens = ["WEB: Caret context is", obj, ", ", offset, + "(focus: ", cthulhu_state.locusOfFocus, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not obj or self.utilities.isZombie(obj) and event.source == cthulhu_state.locusOfFocus: + msg = "WEB: Setting caret context to event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.setCaretContext(event.source, 0) + + return False + + def onFocus(self, event): + """Callback for focus: accessibility events.""" + + # We should get proper state-changed events for these. + if self.utilities.inDocumentContent(event.source): + msg = "WEB: Ignoring because object:state-changed-focused expected." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onFocusedChanged(self, event): + """Callback for object:state-changed:focused accessibility events.""" + + if not event.detail1: + msg = "WEB: Ignoring because event source lost focus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isZombie(event.source): + msg = "WEB: Event source is Zombie" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + document = self.utilities.getDocumentForObject(event.source) + if not document: + msg = "WEB: Could not get document for event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + prevDocument = self.utilities.getDocumentForObject(cthulhu_state.locusOfFocus) + if prevDocument != document: + tokens = ["WEB: document changed from", prevDocument, "to", document] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if self.utilities.isWebAppDescendant(event.source): + if self._browseModeIsSticky: + msg = "WEB: Web app descendant claimed focus, but browse mode is sticky" + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif AXUtilities.is_tool_tip(event.source) \ + and AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.source): + msg = "WEB: Event believed to be side effect of tooltip navigation." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + else: + msg = "WEB: Event handled: Setting locusOfFocus to web app descendant" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source) + return True + + if AXUtilities.is_editable(event.source): + msg = "WEB: Event source is editable" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if AXUtilities.is_dialog_or_alert(event.source): + msg = "WEB: Event handled: Setting locusOfFocus to event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, event.source) + return True + + if self.utilities.handleEventFromContextReplicant(event, event.source): + msg = "WEB: Event handled by updating locusOfFocus and context to source." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + obj, offset = self.utilities.getCaretContext() + tokens = ["WEB: Caret context is", obj, ", ", offset, + "(focus: ", cthulhu_state.locusOfFocus, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not obj or self.utilities.isZombie(obj) or prevDocument != document: + tokens = ["WEB: Clearing context - obj", obj, "is null or zombie or document changed"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.utilities.clearCaretContext() + + obj, offset = self.utilities.searchForCaretContext(event.source) + if obj: + notify = self.utilities.inFindContainer(cthulhu_state.locusOfFocus) + tokens = ["WEB: Updating focus and context to", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj, notify) + if not notify and prevDocument is None: + self.refreshKeyGrabs() + self.utilities.setCaretContext(obj, offset) + else: + msg = "WEB: Search for caret context failed" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if self._lastCommandWasCaretNav: + msg = "WEB: Event ignored: Last command was caret nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self._lastCommandWasStructNav: + msg = "WEB: Event ignored: Last command was struct nav" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not (AXUtilities.is_focusable(event.source) and AXUtilities.is_focused(event.source)): + msg = "WEB: Event ignored: Source is not focusable or focused" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not AXUtilities.is_document(event.source): + msg = "WEB: Deferring to other scripts for handling non-document source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not obj: + msg = "WEB: Unable to get non-null, non-zombie context object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.utilities.lastInputEventWasPageNav(): + msg = "WEB: Event handled: Focus changed due to scrolling" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(event, obj) + self.utilities.setCaretContext(obj, offset) + return True + + wasFocused = AXUtilities.is_focused(obj) + AXObject.clear_cache(obj) + isFocused = AXUtilities.is_focused(obj) + if wasFocused != isFocused: + tokens = ["WEB: Focused state of", obj, "changed to", isFocused] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if self.utilities.isAnchor(obj): + cause = "Context is anchor" + elif not (self.utilities.isLink(obj) and not isFocused): + cause = "Context is not a non-focused link" + elif self.utilities.isChildOfCurrentFragment(obj): + cause = "Context is child of current fragment" + elif document == event.source and self.utilities.documentFragment(event.source): + cause = "Document URI is fragment" + else: + return False + + tokens = ["WEB: Event handled: Setting locusOfFocus to", obj, "(", cause, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, obj) + return True + + def onMouseButton(self, event): + """Callback for mouse:button accessibility events.""" + + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = True + return False + + def onNameChanged(self, event): + """Callback for object:property-change:accessible-name events.""" + + if self.utilities.eventIsBrowserUINoise(event): + msg = "WEB: Ignoring event believed to be browser UI noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return True + + def onRowReordered(self, event): + """Callback for object:row-reordered accessibility events.""" + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if event.source != self.utilities.getTable(cthulhu_state.locusOfFocus): + tokens = ["WEB: locusOfFocus (", cthulhu_state.locusOfFocus, ") is not in this table"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + self.pointOfReference['last-table-sort-time'] = time.time() + self.presentMessage(messages.TABLE_REORDERED_ROWS) + header = self.utilities.containingTableHeader(cthulhu_state.locusOfFocus) + if header: + self.presentMessage(self.utilities.getSortOrderDescription(header, True)) + + return True + + def onSelectedChanged(self, event): + """Callback for object:state-changed:selected accessibility events.""" + + if self.utilities.eventIsBrowserUIAutocompleteNoise(event): + msg = "WEB: Ignoring event believed to be browser UI autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsBrowserUIPageSwitch(event): + msg = "WEB: Event believed to be browser UI page switch" + debug.printMessage(debug.LEVEL_INFO, msg, True) + if event.detail1: + self.presentObject(event.source, priorObj=cthulhu_state.locusOfFocus, interrupt=True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if cthulhu_state.locusOfFocus != event.source: + msg = "WEB: Ignoring because event source is not locusOfFocus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onSelectionChanged(self, event): + """Callback for object:selection-changed accessibility events.""" + + if self.utilities.eventIsBrowserUIAutocompleteNoise(event): + msg = "WEB: Ignoring event believed to be browser UI autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsBrowserUIPageSwitch(event): + msg = "WEB: Ignoring event believed to be browser UI page switch" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not self.utilities.inDocumentContent(cthulhu_state.locusOfFocus): + tokens = ["WEB: Event ignored: locusOfFocus", cthulhu_state.locusOfFocus, + "is not in document content"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if not self.utilities.eventIsFromLocusOfFocusDocument(event): + msg = "WEB: Event ignored: Not from locus of focus document" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isWebAppDescendant(event.source): + if self._inFocusMode: + # Because we cannot count on the app firing the right state-changed events + # for descendants. + AXObject.clear_cache(event.source) + msg = "WEB: Event source is web app descendant and we're in focus mode" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + msg = "WEB: Event source is web app descendant and we're in browse mode" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsIrrelevantSelectionChangedEvent(event): + msg = "WEB: Event ignored: Irrelevant" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + obj, offset = self.utilities.getCaretContext() + ancestor = self.utilities.commonAncestor(obj, event.source) + if ancestor and self.utilities.isTextBlockElement(ancestor): + msg = "WEB: Ignoring: Common ancestor of context and event source is text block" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onShowingChanged(self, event): + """Callback for object:state-changed:showing accessibility events.""" + + if event.detail1 and self.utilities.isTopLevelBrowserUIAlert(event.source): + msg = "WEB: Event handled: Presenting event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.presentObject(event.source, interrupt=True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + return True + + def onTextAttributesChanged(self, event): + """Callback for object:text-attributes-changed accessibility events.""" + + msg = "WEB: Clearing cached text attributes" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._currentTextAttrs = {} + return False + + def onTextDeleted(self, event): + """Callback for object:text-changed:delete accessibility events.""" + + if self.utilities.isZombie(event.source): + msg = "WEB: Event source is Zombie" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.lastInputEventWasPageSwitch(): + msg = "WEB: Deletion is believed to be due to page switch" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isLiveRegion(event.source): + msg = "WEB: Ignoring deletion from live region" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsBrowserUINoise(event): + msg = "WEB: Ignoring event believed to be browser UI noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.utilities.eventIsSpinnerNoise(event): + msg = "WEB: Ignoring: Event believed to be spinner noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsAutocompleteNoise(event): + msg = "WEB: Ignoring event believed to be autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "WEB: Clearing content cache due to text deletion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.clearContentCache() + + if self.utilities.textEventIsDueToDeletion(event): + msg = "WEB: Event believed to be due to editable text deletion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.utilities.textEventIsDueToInsertion(event): + msg = "WEB: Ignoring event believed to be due to text insertion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + obj, offset = self.utilities.getCaretContext(getZombieReplicant=False) + if obj and obj != event.source \ + and not AXObject.find_ancestor(obj, lambda x: x == event.source): + tokens = ["WEB: Ignoring event because it isn't", obj, "or its ancestor"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self.utilities.isZombie(obj): + if self.utilities.isLink(obj): + msg = "WEB: Focused link deleted. Taking no further action." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + obj, offset = self.utilities.getCaretContext(getZombieReplicant=True) + if obj: + cthulhu.setLocusOfFocus(event, obj, notifyScript=False) + + if self.utilities.isZombie(obj): + msg = "WEB: Unable to get non-null, non-zombie context object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + document = self.utilities.getDocumentForObject(event.source) + if document: + tokens = ["WEB: Clearing structural navigation cache for", document] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.structuralNavigation.clearCache(document) + + if not AXUtilities.is_editable(event.source) \ + and not self.utilities.isContentEditableWithEmbeddedObjects(event.source): + if self._inMouseOverObject \ + and self.utilities.isZombie(self._lastMouseOverObject): + msg = "WEB: Restoring pre-mouseover context" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.restorePreMouseOverContext() + + msg = "WEB: Done processing non-editable source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onTextInserted(self, event): + """Callback for object:text-changed:insert accessibility events.""" + + if self.utilities.isZombie(event.source): + msg = "WEB: Event source is Zombie" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.lastInputEventWasPageSwitch(): + msg = "WEB: Insertion is believed to be due to page switch" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.handleAsLiveRegion(event): + msg = "WEB: Event to be handled as live region" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.liveRegionManager.handleEvent(event) + return True + + if self.utilities.isLiveRegion(event.source): + msg = "WEB: Ignoring because live region event not to be handled." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsEOCAdded(event): + msg = "WEB: Ignoring: Event was for embedded object char" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsBrowserUINoise(event): + msg = "WEB: Ignoring event believed to be browser UI noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self.utilities.eventIsSpinnerNoise(event): + msg = "WEB: Ignoring: Event believed to be spinner noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsAutocompleteNoise(event): + msg = "WEB: Ignoring: Event believed to be autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + msg = "WEB: Clearing content cache due to text insertion" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.clearContentCache() + + document = self.utilities.getTopLevelDocumentForObject(event.source) + if AXObject.is_dead(cthulhu_state.locusOfFocus): + msg = "WEB: Dumping cache: dead focus" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.utilities.dumpCache(document, preserveContext=True) + + if AXUtilities.is_focused(event.source): + msg = "WEB: Event handled: Setting locusOfFocus to event source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(None, event.source, force=True) + return True + + else: + tokens = ["WEB: Clearing structural navigation cache for", document] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.structuralNavigation.clearCache(document) + + text = self.utilities.queryNonEmptyText(event.source) + if not text: + msg = "WEB: Ignoring: Event source is not a text object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not AXUtilities.is_editable(event.source): + if event.source != cthulhu_state.locusOfFocus: + msg = "WEB: Done processing non-editable, non-locusOfFocus source" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isClickableElement(event.source): + msg = "WEB: Event handled: Re-setting locusOfFocus to changed clickable" + debug.printMessage(debug.LEVEL_INFO, msg, True) + cthulhu.setLocusOfFocus(None, event.source, force=True) + return True + + if AXUtilities.is_text_input(event.source) \ + and AXUtilities.is_focused(event.source) \ + and event.source != cthulhu_state.locusOfFocus: + msg = "WEB: Focused entry is not the locus of focus. Waiting for focus event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onTextSelectionChanged(self, event): + """Callback for object:text-selection-changed accessibility events.""" + + if self.utilities.isZombie(event.source): + msg = "WEB: Event source is Zombie" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsBrowserUINoise(event): + msg = "WEB: Ignoring event believed to be browser UI noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if not self.utilities.inDocumentContent(event.source): + msg = "WEB: Event source is not in document content" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not self.utilities.inDocumentContent(cthulhu_state.locusOfFocus): + tokens = ["WEB: Event ignored: locusOfFocus", cthulhu_state.locusOfFocus, + "is not in document content"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self.utilities.eventIsAutocompleteNoise(event): + msg = "WEB: Ignoring: Event believed to be autocomplete noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.eventIsSpinnerNoise(event): + msg = "WEB: Ignoring: Event believed to be spinner noise" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.textEventIsForNonNavigableTextObject(event): + msg = "WEB: Ignoring event for non-navigable text object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + text = self.utilities.queryNonEmptyText(event.source) + if not text: + msg = "WEB: Ignoring: Event source is not a text object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if AXUtilities.is_text_input(event.source) \ + and AXUtilities.is_focused(event.source) \ + and event.source != cthulhu_state.locusOfFocus: + msg = "WEB: Focused entry is not the locus of focus. Waiting for focus event." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + if self.utilities.isContentEditableWithEmbeddedObjects(event.source): + msg = "WEB: In content editable with embedded objects" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + offset = text.caretOffset + char = text.getText(offset, offset+1) + if char == self.EMBEDDED_OBJECT_CHARACTER \ + and not self.utilities.lastInputEventWasCaretNavWithSelection() \ + and not self.utilities.lastInputEventWasCommand(): + msg = "WEB: Ignoring: Not selecting and event offset is at embedded object" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def onWindowActivated(self, event): + """Callback for window:activate accessibility events.""" + + msg = "WEB: Deferring to app/toolkit script" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def onWindowDeactivated(self, event): + """Callback for window:deactivate accessibility events.""" + + msg = "WEB: Clearing command state" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self._lastCommandWasCaretNav = False + self._lastCommandWasStructNav = False + self._lastCommandWasMouseButton = False + self._lastMouseButtonContext = None, -1 + self.removeKeyGrabs() + return False + + def getTransferableAttributes(self): + return {"_lastCommandWasCaretNav": self._lastCommandWasCaretNav, + "_lastCommandWasStructNav": self._lastCommandWasStructNav, + "_lastCommandWasMouseButton": self._lastCommandWasMouseButton, + "_inFocusMode": self._inFocusMode, + "_focusModeIsSticky": self._focusModeIsSticky, + "_browseModeIsSticky": self._browseModeIsSticky, + } diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script_utilities.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script_utilities.py new file mode 100644 index 0000000..795bf77 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/script_utilities.py @@ -0,0 +1,5515 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Joanmarie Diggs." \ + "Copyright (c) 2014-2015 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import functools +import re +import time +import urllib + +from cthulhu import debug +from cthulhu import input_event +from cthulhu import messages +from cthulhu import cthulhu +from cthulhu import cthulhu_state +from cthulhu import script_utilities +from cthulhu import script_manager +from cthulhu import settings_manager +from cthulhu.ax_collection import AXCollection +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_scriptManager = script_manager.getManager() +_settingsManager = settings_manager.getManager() + + +class Utilities(script_utilities.Utilities): + + def __init__(self, script): + super().__init__(script) + + self._objectAttributes = {} + self._currentTextAttrs = {} + self._caretContexts = {} + self._priorContexts = {} + self._canHaveCaretContextDecision = {} + self._contextPathsRolesAndNames = {} + self._paths = {} + self._inDocumentContent = {} + self._inTopLevelWebApp = {} + self._isTextBlockElement = {} + self._isContentEditableWithEmbeddedObjects = {} + self._isCodeDescendant = {} + self._isEntryDescendant = {} + self._hasGridDescendant = {} + self._isGridDescendant = {} + self._isLabelDescendant = {} + self._isModalDialogDescendant = {} + self._isMenuDescendant = {} + self._isNavigableToolTipDescendant = {} + self._isToolBarDescendant = {} + self._isWebAppDescendant = {} + self._isLayoutOnly = {} + self._isFocusableWithMathChild = {} + self._mathNestingLevel = {} + self._isOffScreenLabel = {} + self._labelIsAncestorOfLabelled = {} + self._elementLinesAreSingleChars= {} + self._elementLinesAreSingleWords= {} + self._hasNoSize = {} + self._hasLongDesc = {} + self._hasVisibleCaption = {} + self._hasDetails = {} + self._isDetails = {} + self._isNonInteractiveDescendantOfControl = {} + self._isClickableElement = {} + self._isAnchor = {} + self._isEditableComboBox = {} + self._isErrorMessage = {} + self._isInlineIframeDescendant = {} + self._isInlineListItem = {} + self._isInlineListDescendant = {} + self._isLandmark = {} + self._isLink = {} + self._isListDescendant = {} + self._isNonNavigablePopup = {} + self._isNonEntryTextWidget = {} + self._isCustomImage = {} + self._isUselessImage = {} + self._isRedundantSVG = {} + self._isUselessEmptyElement = {} + self._hasNameAndActionAndNoUsefulChildren = {} + self._isNonNavigableEmbeddedDocument = {} + self._isParentOfNullChild = {} + self._inferredLabels = {} + self._labelsForObject = {} + self._labelTargets = {} + self._descriptionListTerms = {} + self._valuesForTerm = {} + self._displayedLabelText = {} + self._mimeType = {} + self._preferDescriptionOverName = {} + self._shouldFilter = {} + self._shouldInferLabelFor = {} + self._treatAsTextObject = {} + self._treatAsDiv = {} + self._currentObjectContents = None + self._currentSentenceContents = None + self._currentLineContents = None + self._currentWordContents = None + self._currentCharacterContents = None + self._lastQueuedLiveRegionEvent = None + self._findContainer = None + self._validChildRoles = {Atspi.Role.LIST: [Atspi.Role.LIST_ITEM]} + + def _cleanupContexts(self): + toRemove = [] + for key, [obj, offset] in self._caretContexts.items(): + if self.isZombie(obj): + toRemove.append(key) + + for key in toRemove: + self._caretContexts.pop(key, None) + + def dumpCache(self, documentFrame=None, preserveContext=False): + if not documentFrame or self.isZombie(documentFrame): + documentFrame = self.documentFrame() + + documentFrameParent = AXObject.get_parent(documentFrame) + context = self._caretContexts.get(hash(documentFrameParent)) + + tokens = ["WEB: Clearing all cached info for", documentFrame] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._script.structuralNavigation.clearCache(documentFrame) + self.clearCaretContext(documentFrame) + self.clearCachedObjects() + + if preserveContext and context: + tokens = ["WEB: Preserving context of", context[0], ",", context[1]] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._caretContexts[hash(documentFrameParent)] = context + + def clearCachedObjects(self): + debug.printMessage(debug.LEVEL_INFO, "WEB: cleaning up cached objects", True) + self._objectAttributes = {} + self._inDocumentContent = {} + self._inTopLevelWebApp = {} + self._isTextBlockElement = {} + self._isContentEditableWithEmbeddedObjects = {} + self._isCodeDescendant = {} + self._isEntryDescendant = {} + self._hasGridDescendant = {} + self._isGridDescendant = {} + self._isLabelDescendant = {} + self._isMenuDescendant = {} + self._isModalDialogDescendant = {} + self._isNavigableToolTipDescendant = {} + self._isToolBarDescendant = {} + self._isWebAppDescendant = {} + self._isLayoutOnly = {} + self._isFocusableWithMathChild = {} + self._mathNestingLevel = {} + self._isOffScreenLabel = {} + self._labelIsAncestorOfLabelled = {} + self._elementLinesAreSingleChars= {} + self._elementLinesAreSingleWords= {} + self._hasNoSize = {} + self._hasLongDesc = {} + self._hasVisibleCaption = {} + self._hasDetails = {} + self._isDetails = {} + self._isNonInteractiveDescendantOfControl = {} + self._isClickableElement = {} + self._isAnchor = {} + self._isEditableComboBox = {} + self._isErrorMessage = {} + self._isInlineIframeDescendant = {} + self._isInlineListItem = {} + self._isInlineListDescendant = {} + self._isLandmark = {} + self._isLink = {} + self._isListDescendant = {} + self._isNonNavigablePopup = {} + self._isNonEntryTextWidget = {} + self._isCustomImage = {} + self._isUselessImage = {} + self._isRedundantSVG = {} + self._isUselessEmptyElement = {} + self._hasNameAndActionAndNoUsefulChildren = {} + self._isNonNavigableEmbeddedDocument = {} + self._isParentOfNullChild = {} + self._inferredLabels = {} + self._labelsForObject = {} + self._labelTargets = {} + self._descriptionListTerms = {} + self._valuesForTerm = {} + self._displayedLabelText = {} + self._mimeType = {} + self._preferDescriptionOverName = {} + self._shouldFilter = {} + self._shouldInferLabelFor = {} + self._treatAsTextObject = {} + self._treatAsDiv = {} + self._paths = {} + self._contextPathsRolesAndNames = {} + self._canHaveCaretContextDecision = {} + self._cleanupContexts() + self._priorContexts = {} + self._lastQueuedLiveRegionEvent = None + self._findContainer = None + + def clearContentCache(self): + self._currentObjectContents = None + self._currentSentenceContents = None + self._currentLineContents = None + self._currentWordContents = None + self._currentCharacterContents = None + self._currentTextAttrs = {} + + def isDocument(self, obj, excludeDocumentFrame=True): + if AXUtilities.is_document_web(obj) or AXUtilities.is_embedded(obj): + return True + + if not excludeDocumentFrame: + return AXUtilities.is_document_frame(obj) + + return False + + def inDocumentContent(self, obj=None): + if not obj: + obj = cthulhu_state.locusOfFocus + + if self.isDocument(obj): + return True + + rv = self._inDocumentContent.get(hash(obj)) + if rv is not None: + return rv + + document = self.getDocumentForObject(obj) + rv = document is not None + self._inDocumentContent[hash(obj)] = rv + return rv + + def _getDocumentsEmbeddedBy(self, frame): + return AXObject.get_relation_targets(frame, Atspi.RelationType.EMBEDS, self.isDocument) + + def sanityCheckActiveWindow(self): + app = self._script.app + if AXObject.get_parent(cthulhu_state.activeWindow) == app: + return True + + tokens = ["WARNING:", cthulhu_state.activeWindow, "is not child of", app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + # TODO - JD: Is this exception handling still needed? + try: + script = _scriptManager.getScript(app, cthulhu_state.activeWindow) + tokens = ["WEB: Script for active Window is", script] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception: + msg = "ERROR: Exception getting script for active window" + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + if isinstance(script, type(self._script)): + attrs = script.getTransferableAttributes() + for attr, value in attrs.items(): + tokens = ["WEB: Setting", attr, "to", value] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + setattr(self._script, attr, value) + + window = self.activeWindow(app) + self._script.app = AXObject.get_application(window) + tokens = ["WEB: updating script's app to", self._script.app] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + cthulhu.setActiveWindow(window) + return True + + def activeDocument(self, window=None): + documents = self._getDocumentsEmbeddedBy(window or cthulhu_state.activeWindow) + documents = list(filter(AXUtilities.is_showing, documents)) + if len(documents) == 1: + return documents[0] + return None + + def documentFrame(self, obj=None): + if not obj and self.sanityCheckActiveWindow(): + document = self.activeDocument() + if document: + return document + + return self.getDocumentForObject(obj or cthulhu_state.locusOfFocus) + + def documentFrameURI(self, documentFrame=None): + documentFrame = documentFrame or self.documentFrame() + if documentFrame: + try: + document = documentFrame.queryDocument() + except NotImplementedError: + tokens = ["WEB:", documentFrame, "does not implement document interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception: + tokens = ["ERROR: Exception querying document interface of", documentFrame] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + return document.getAttributeValue('DocURL') or document.getAttributeValue('URI') + + return "" + + def isPlainText(self, documentFrame=None): + return self.mimeType(documentFrame) == "text/plain" + + def mimeType(self, documentFrame=None): + documentFrame = documentFrame or self.documentFrame() + rv = self._mimeType.get(hash(documentFrame)) + if rv is not None: + return rv + + try: + document = documentFrame.queryDocument() + attrs = dict([attr.split(":", 1) for attr in document.getAttributes()]) + except NotImplementedError: + tokens = ["WEB:", documentFrame, "does not implement document interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception: + tokens = ["ERROR: Exception getting document attributes of", documentFrame] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + rv = attrs.get("MimeType") + tokens = ["WEB: MimeType of", documentFrame, "is '", rv, "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._mimeType[hash(documentFrame)] = rv + + return rv + + def grabFocusWhenSettingCaret(self, obj): + # To avoid triggering popup lists. + if AXUtilities.is_entry(obj): + return False + + if AXUtilities.is_image(obj): + return AXObject.find_ancestor(obj, AXUtilities.is_link) is not None + + if AXUtilities.is_heading(obj) and AXObject.get_child_count(obj) == 1: + return self.isLink(AXObject.get_child(obj, 0)) + + return AXUtilities.is_focusable(obj) + + def grabFocus(self, obj): + try: + obj.queryComponent().grabFocus() + except NotImplementedError: + tokens = ["WEB:", obj, "does not implement the component interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception: + tokens = ["WEB: Exception grabbing focus on", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def setCaretPosition(self, obj, offset, documentFrame=None): + if self._script.flatReviewPresenter.is_active(): + self._script.flatReviewPresenter.quit() + grabFocus = self.grabFocusWhenSettingCaret(obj) + + obj, offset = self.findFirstCaretContext(obj, offset) + self.setCaretContext(obj, offset, documentFrame) + if self._script.focusModeIsSticky(): + return + + oldFocus = cthulhu_state.locusOfFocus + self.clearTextSelection(oldFocus) + cthulhu.setLocusOfFocus(None, obj, notifyScript=False) + if grabFocus: + self.grabFocus(obj) + + # Don't use queryNonEmptyText() because we need to try to force-update focus. + if AXObject.supports_text(obj): + try: + obj.queryText().setCaretOffset(offset) + except Exception as error: + tokens = ["WEB: Exception setting caret to", offset, "in", obj, ":", error] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + tokens = ["WEB: Caret set to", offset, "in", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if self._script.useFocusMode(obj, oldFocus) != self._script.inFocusMode(): + self._script.togglePresentationMode(None) + + if obj: + AXObject.clear_cache(obj) + + # TODO - JD: This is private. + self._script._saveFocusedObjectInfo(obj) + + def getNextObjectInDocument(self, obj, documentFrame): + if not obj: + return None + + relation = AXObject.get_relation(obj, Atspi.RelationType.FLOWS_TO) + if relation: + return relation.get_target(0) + + if obj == documentFrame: + obj, offset = self.getCaretContext(documentFrame) + for child in AXObject.iter_children(documentFrame): + if self.characterOffsetInParent(child) > offset: + return child + + if AXObject.get_child_count(obj): + return AXObject.get_child(obj, 0) + + while obj and obj != documentFrame: + nextObj = AXObject.get_next_sibling(obj) + if nextObj: + return nextObj + obj = AXObject.get_parent(obj) + + return None + + def getLastObjectInDocument(self, documentFrame): + return AXObject.find_deepest_descendant(documentFrame) + + def objectAttributes(self, obj, useCache=True): + if not (obj and self.inDocumentContent(obj)): + return super().objectAttributes(obj) + + if useCache: + rv = self._objectAttributes.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.get_attributes_dict(obj) + self._objectAttributes[hash(obj)] = rv + return rv + + def getRoleDescription(self, obj, isBraille=False): + attrs = self.objectAttributes(obj) + rv = attrs.get('roledescription', '') + if isBraille: + rv = attrs.get('brailleroledescription', rv) + + return rv + + def nodeLevel(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().nodeLevel(obj) + + rv = -1 + if not (self.inMenu(obj) or AXUtilities.is_heading(obj)): + attrs = self.objectAttributes(obj) + # ARIA levels are 1-based; non-web content is 0-based. Be consistent. + rv = int(attrs.get('level', 0)) -1 + + return rv + + def _shouldCalculatePositionAndSetSize(self, obj): + return True + + def getPositionAndSetSize(self, obj, **args): + posinset = self.getPositionInSet(obj) + setsize = self.getSetSize(obj) + if posinset is not None and setsize is not None: + # ARIA posinset is 1-based + return posinset - 1, setsize + + if self._shouldCalculatePositionAndSetSize(obj): + return super().getPositionAndSetSize(obj, **args) + + return -1, -1 + + def getPositionInSet(self, obj): + attrs = self.objectAttributes(obj, False) + position = attrs.get('posinset') + if position is not None: + return int(position) + + if AXUtilities.is_table_row(obj): + rowindex = attrs.get('rowindex') + if rowindex is None and AXObject.get_child_count(obj): + cell = AXObject.find_descendant(obj, AXUtilities.is_table_cell_or_header) + rowindex = self.objectAttributes(cell, False).get('rowindex') + + if rowindex is not None: + return int(rowindex) + + return None + + def getSetSize(self, obj): + attrs = self.objectAttributes(obj, False) + setsize = attrs.get('setsize') + if setsize is not None: + return int(setsize) + + if AXUtilities.is_table_row(obj): + rows, cols = self.rowAndColumnCount(self.getTable(obj)) + if rows != -1: + return rows + + return None + + def _getID(self, obj): + attrs = self.objectAttributes(obj) + return attrs.get('id') + + def _getDisplayStyle(self, obj): + attrs = self.objectAttributes(obj) + return attrs.get('display', '') + + def _getTag(self, obj): + attrs = self.objectAttributes(obj) + return attrs.get('tag') + + def _getXMLRoles(self, obj): + attrs = self.objectAttributes(obj) + return attrs.get('xml-roles', '').split() + + def inFindContainer(self, obj=None): + if not obj: + obj = cthulhu_state.locusOfFocus + + if self.inDocumentContent(obj): + return False + + return super().inFindContainer(obj) + + def isEmpty(self, obj): + if not self.isTextBlockElement(obj): + return False + + if AXObject.get_name(obj): + return False + + return self.queryNonEmptyText(obj, False) is None + + def isHidden(self, obj): + attrs = self.objectAttributes(obj, False) + return attrs.get('hidden', False) + + def _isOrIsIn(self, child, parent): + if not (child and parent): + return False + + if child == parent: + return True + + return AXObject.find_ancestor(child, lambda x: x == parent) + + def isShowingAndVisible(self, obj): + rv = super().isShowingAndVisible(obj) + if rv or not self.inDocumentContent(obj): + return rv + + if not self._script.mouseReviewer.inMouseEvent: + if not self._isOrIsIn(cthulhu_state.locusOfFocus, obj): + return rv + + tokens = ["WEB:", obj, "contains locusOfFocus but not showing and visible"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + AXObject.clear_cache(obj) + rv = super().isShowingAndVisible(obj) + if rv: + tokens = ["WEB: Clearing cache fixed state of", obj, ". Missing event?"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return rv + + def isTextArea(self, obj): + if not self.inDocumentContent(obj): + return super().isTextArea(obj) + + if self.isLink(obj): + return False + + if AXUtilities.is_combo_box(obj) \ + and AXUtilities.is_editable(obj) \ + and not AXObject.get_child_count(obj): + return True + + if AXObject.get_role(obj) in self._textBlockElementRoles(): + document = self.getDocumentForObject(obj) + if AXUtilities.is_editable(document): + return True + + return super().isTextArea(obj) + + def isReadOnlyTextArea(self, obj): + # NOTE: This method is deliberately more conservative than isTextArea. + if not AXUtilities.is_entry(obj): + return False + + if AXUtilities.is_read_only(obj): + return True + + return AXUtilities.is_focusable(obj) and not AXUtilities.is_editable(obj) + + def setCaretOffset(self, obj, characterOffset): + self.setCaretPosition(obj, characterOffset) + self._script.updateBraille(obj) + + def nextContext(self, obj=None, offset=-1, skipSpace=False): + if not obj: + obj, offset = self.getCaretContext() + + nextobj, nextoffset = self.findNextCaretInOrder(obj, offset) + if skipSpace: + text = self.queryNonEmptyText(nextobj) + while text and text.getText(nextoffset, nextoffset + 1) in [" ", "\xa0"]: + nextobj, nextoffset = self.findNextCaretInOrder(nextobj, nextoffset) + text = self.queryNonEmptyText(nextobj) + + return nextobj, nextoffset + + def previousContext(self, obj=None, offset=-1, skipSpace=False): + if not obj: + obj, offset = self.getCaretContext() + + prevobj, prevoffset = self.findPreviousCaretInOrder(obj, offset) + if skipSpace: + text = self.queryNonEmptyText(prevobj) + while text and text.getText(prevoffset, prevoffset + 1) in [" ", "\xa0"]: + prevobj, prevoffset = self.findPreviousCaretInOrder(prevobj, prevoffset) + text = self.queryNonEmptyText(prevobj) + + return prevobj, prevoffset + + def lastContext(self, root): + offset = 0 + text = self.queryNonEmptyText(root) + if text: + offset = text.characterCount - 1 + + def _isInRoot(o): + return o == root or AXObject.find_ancestor(o, lambda x: x == root) + + obj = root + while obj: + lastobj, lastoffset = self.nextContext(obj, offset) + if not (lastobj and _isInRoot(lastobj)): + break + obj, offset = lastobj, lastoffset + + return obj, offset + + def contextsAreOnSameLine(self, a, b): + if a == b: + return True + + aObj, aOffset = a + bObj, bOffset = b + aExtents = self.getExtents(aObj, aOffset, aOffset + 1) + bExtents = self.getExtents(bObj, bOffset, bOffset + 1) + return self.extentsAreOnSameLine(aExtents, bExtents) + + @staticmethod + def extentsAreOnSameLine(a, b, pixelDelta=5): + if a == b: + return True + + aX, aY, aWidth, aHeight = a + bX, bY, bWidth, bHeight = b + + if aWidth == 0 and aHeight == 0: + return bY <= aY <= bY + bHeight + if bWidth == 0 and bHeight == 0: + return aY <= bY <= aY + aHeight + + highestBottom = min(aY + aHeight, bY + bHeight) + lowestTop = max(aY, bY) + if lowestTop >= highestBottom: + return False + + aMiddle = aY + aHeight / 2 + bMiddle = bY + bHeight / 2 + if abs(aMiddle - bMiddle) > pixelDelta: + return False + + return True + + @staticmethod + def getExtents(obj, startOffset, endOffset): + if not obj: + return [0, 0, 0, 0] + + result = [0, 0, 0, 0] + try: + text = obj.queryText() + if text.characterCount and 0 <= startOffset < endOffset: + result = list(text.getRangeExtents(startOffset, endOffset, 0)) + except NotImplementedError: + pass + except Exception: + tokens = ["WEB: Exception getting range extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [0, 0, 0, 0] + else: + if result[0] and result[1] and result[2] == 0 and result[3] == 0 \ + and text.getText(startOffset, endOffset).strip(): + tokens = ["WEB: Suspected bogus range extents for", + obj, "(chars:", startOffset, ",", endOffset, "):", result] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + elif text.characterCount: + return result + + parent = AXObject.get_parent(obj) + if (AXUtilities.is_menu(obj) or AXUtilities.is_list_item(obj)) \ + and (AXUtilities.is_combo_box(parent) or AXUtilities.is_list_box(parent)): + try: + ext = parent.queryComponent().getExtents(0) + except NotImplementedError: + tokens = ["WEB:", parent, "does not implement the component interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [0, 0, 0, 0] + except Exception: + tokens = ["WEB: Exception getting extents for", parent] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [0, 0, 0, 0] + else: + try: + ext = obj.queryComponent().getExtents(0) + except NotImplementedError: + tokens = ["WEB:", obj, "does not implement the component interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [0, 0, 0, 0] + except Exception: + tokens = ["WEB: Exception getting extents for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [0, 0, 0, 0] + + return [ext.x, ext.y, ext.width, ext.height] + + def descendantAtPoint(self, root, x, y, coordType=None): + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + result = None + if self.isDocument(root): + result = self.accessibleAtPoint(root, x, y, coordType) + + if result is None: + result = super().descendantAtPoint(root, x, y, coordType) + + if self.isListItemMarker(result) or self.isStaticTextLeaf(result): + return AXObject.get_parent(result) + + return result + + def _preserveTree(self, obj): + if not (obj and AXObject.get_child_count(obj)): + return False + + if self.isMathTopLevel(obj): + return True + + return False + + def expandEOCs(self, obj, startOffset=0, endOffset=-1): + if not self.inDocumentContent(obj): + return super().expandEOCs(obj, startOffset, endOffset) + + if self.hasGridDescendant(obj): + tokens = ["WEB: not expanding EOCs:", obj, "has grid descendant"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + + text = self.queryNonEmptyText(obj) + if not text: + return "" + + if self._preserveTree(obj): + utterances = self._script.speechGenerator.generateSpeech(obj) + return self._script.speechGenerator.utterancesToString(utterances) + + return super().expandEOCs(obj, startOffset, endOffset).strip() + + def substring(self, obj, startOffset, endOffset): + if not self.inDocumentContent(obj): + return super().substring(obj, startOffset, endOffset) + + text = self.queryNonEmptyText(obj) + if text: + return text.getText(startOffset, endOffset) + + return "" + + def textAttributes(self, acc, offset, get_defaults=False): + attrsForObj = self._currentTextAttrs.get(hash(acc)) or {} + if offset in attrsForObj: + return attrsForObj.get(offset) + + attrs = super().textAttributes(acc, offset, get_defaults) + objAttributes = self.objectAttributes(acc, False) + for key in self._script.attributeNamesDict.keys(): + value = objAttributes.get(key) + if value is not None: + attrs[0][key] = value + + self._currentTextAttrs[hash(acc)] = {offset:attrs} + return attrs + + def localizeTextAttribute(self, key, value): + if key == "justification" and value == "justify": + value = "fill" + + return super().localizeTextAttribute(key, value) + + def adjustContentsForLanguage(self, contents): + rv = [] + for content in contents: + split = self.splitSubstringByLanguage(*content[0:3]) + for start, end, string, language, dialect in split: + rv.append([content[0], start, end, string]) + + return rv + + def getLanguageAndDialectFromTextAttributes(self, obj, startOffset=0, endOffset=-1): + rv = super().getLanguageAndDialectFromTextAttributes(obj, startOffset, endOffset) + if rv or obj is None: + return rv + + # Embedded objects such as images and certain widgets won't implement the text interface + # and thus won't expose text attributes. Therefore try to get the info from the parent. + parent = AXObject.get_parent(obj) + if parent is None: + return rv + + start, end = self.getHyperlinkRange(obj) + language, dialect = self.getLanguageAndDialectForSubstring(parent, start, end) + rv.append((0, 1, language, dialect)) + + return rv + + def findObjectInContents(self, obj, offset, contents, usingCache=False): + if not obj or not contents: + return -1 + + offset = max(0, offset) + matches = [x for x in contents if x[0] == obj] + match = [x for x in matches if x[1] <= offset < x[2]] + if match and match[0] and match[0] in contents: + return contents.index(match[0]) + if not usingCache: + match = [x for x in matches if offset == x[2]] + if match and match[0] and match[0] in contents: + return contents.index(match[0]) + + if not self.isTextBlockElement(obj): + return -1 + + child = self.findChildAtOffset(obj, offset) + if child and not self.isTextBlockElement(child): + matches = [x for x in contents if x[0] == child] + if len(matches) == 1: + return contents.index(matches[0]) + + return -1 + + def findPreviousObject(self, obj): + result = super().findPreviousObject(obj) + if not (obj and self.inDocumentContent(obj)): + return result + + if not (result and self.inDocumentContent(result)): + return None + + if self.getTopLevelDocumentForObject(result) != self.getTopLevelDocumentForObject(obj): + return None + + tokens = ["WEB: Previous object for", obj, "is", result, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + def findNextObject(self, obj): + result = super().findNextObject(obj) + if not (obj and self.inDocumentContent(obj)): + return result + + if not (result and self.inDocumentContent(result)): + return None + + if self.getTopLevelDocumentForObject(result) != self.getTopLevelDocumentForObject(obj): + return None + + tokens = ["WEB: Next object for", obj, "is", result, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + def isNonEntryTextWidget(self, obj): + rv = self._isNonEntryTextWidget.get(hash(obj)) + if rv is not None: + return rv + + roles = [Atspi.Role.CHECK_BOX, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.PAGE_TAB, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.TOGGLE_BUTTON] + + role = AXObject.get_role(obj) + if role in roles: + rv = True + elif role == Atspi.Role.LIST_ITEM: + rv = not AXUtilities.is_list(AXObject.get_parent(obj)) + elif role == Atspi.Role.TABLE_CELL: + if AXUtilities.is_editable(obj): + rv = False + else: + rv = not self.isTextBlockElement(obj) + + self._isNonEntryTextWidget[hash(obj)] = rv + return rv + + def treatAsTextObject(self, obj, excludeNonEntryTextWidgets=True): + if not obj or AXObject.is_dead(obj): + return False + + rv = self._treatAsTextObject.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.supports_text(obj) + if not rv: + tokens = ["WEB:", obj, "does not implement text interface"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not self.inDocumentContent(obj): + return rv + + if rv and self._treatObjectAsWhole(obj, -1) and AXObject.get_name(obj) \ + and not self.isCellWithNameFromHeader(obj): + tokens = ["WEB: Treating", obj, "as non-text: named object treated as whole."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + + elif rv and not self.isLiveRegion(obj): + doNotQuery = [Atspi.Role.LIST_BOX] + role = AXObject.get_role(obj) + if rv and role in doNotQuery: + tokens = ["WEB: Treating", obj, "as non-text due to role."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + if rv and excludeNonEntryTextWidgets and self.isNonEntryTextWidget(obj): + tokens = ["WEB: Treating", obj, "as non-text: is non-entry text widget."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + if rv and (self.isHidden(obj) or self.isOffScreenLabel(obj)): + tokens = ["WEB: Treating", obj, "as non-text: is hidden or off-screen label."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + if rv and self.isNonNavigableEmbeddedDocument(obj): + tokens = ["WEB: Treating", obj, "as non-text: is non-navigable embedded document."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + if rv and self.isFakePlaceholderForEntry(obj): + tokens = ["WEB: Treating", obj, "as non-text: is fake placeholder for entry."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + + self._treatAsTextObject[hash(obj)] = rv + return rv + + def queryNonEmptyText(self, obj, excludeNonEntryTextWidgets=True): + if self._script.browseModeIsSticky(): + return super().queryNonEmptyText(obj) + + if not self.treatAsTextObject(obj, excludeNonEntryTextWidgets): + return None + + return super().queryNonEmptyText(obj) + + def hasNameAndActionAndNoUsefulChildren(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._hasNameAndActionAndNoUsefulChildren.get(hash(obj)) + if rv is not None: + return rv + + rv = False + if self.hasExplicitName(obj) and AXObject.supports_action(obj): + for child in AXObject.iter_children(obj): + if not self.isUselessEmptyElement(child) or self.isUselessImage(child): + break + else: + rv = True + + if rv: + tokens = ["WEB:", obj, "has name and action and no useful children"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._hasNameAndActionAndNoUsefulChildren[hash(obj)] = rv + return rv + + def isNonInteractiveDescendantOfControl(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isNonInteractiveDescendantOfControl.get(hash(obj)) + if rv is not None: + return rv + + role = AXObject.get_role(obj) + rv = False + roles = self._textBlockElementRoles() + roles.extend([Atspi.Role.IMAGE, Atspi.Role.CANVAS]) + if role in roles and not AXUtilities.is_focusable(obj): + controls = [Atspi.Role.CHECK_BOX, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.LIST_BOX, + Atspi.Role.MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.TOGGLE_BUTTON, + Atspi.Role.TREE_ITEM] + rv = AXObject.find_ancestor(obj, lambda x: AXObject.get_role(x) in controls) + + self._isNonInteractiveDescendantOfControl[hash(obj)] = rv + return rv + + def _treatObjectAsWhole(self, obj, offset=None): + always = [Atspi.Role.CHECK_BOX, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.LIST_BOX, + Atspi.Role.MENU_ITEM, + Atspi.Role.PAGE_TAB, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.RADIO_BUTTON, + Atspi.Role.PUSH_BUTTON, + Atspi.Role.TOGGLE_BUTTON] + + descendable = [Atspi.Role.MENU, + Atspi.Role.MENU_BAR, + Atspi.Role.TOOL_BAR, + Atspi.Role.TREE_ITEM] + + role = AXObject.get_role(obj) + if role in always: + return True + + if role in descendable: + if self._script.inFocusMode(): + return True + + # This should cause us to initially stop at the large containers before + # allowing the user to drill down into them in browse mode. + return offset == -1 + + if role == Atspi.Role.ENTRY: + if AXObject.get_child_count(obj) == 1 \ + and self.isFakePlaceholderForEntry(AXObject.get_child(obj, 0)): + return True + return False + + if AXUtilities.is_editable(obj): + return False + + if role == Atspi.Role.TABLE_CELL: + if self.isFocusModeWidget(obj): + return not self._script.browseModeIsSticky() + if self.hasNameAndActionAndNoUsefulChildren(obj): + return True + + if role in [Atspi.Role.COLUMN_HEADER, Atspi.Role.ROW_HEADER] \ + and self.hasExplicitName(obj): + return True + + if role == Atspi.Role.COMBO_BOX: + return True + + if role in [Atspi.Role.EMBEDDED, Atspi.Role.TREE, Atspi.Role.TREE_TABLE]: + return not self._script.browseModeIsSticky() + + if role == Atspi.Role.LINK: + return self.hasExplicitName(obj) or self.hasUselessCanvasDescendant(obj) + + if self.isNonNavigableEmbeddedDocument(obj): + return True + + if self.isFakePlaceholderForEntry(obj): + return True + + if self.isCustomImage(obj): + return True + + return False + + def __findRange(self, text, offset, start, end, boundary): + # We should not have to do any of this. Seriously. This is why + # We can't have nice things. + + allText = text.getText(0, -1) + if boundary == Atspi.TextBoundaryType.CHAR: + try: + string = allText[offset] + except IndexError: + string = "" + + return string, offset, offset + 1 + + extents = list(text.getRangeExtents(offset, offset + 1, 0)) + + def _inThisSpan(span): + return span[0] <= offset <= span[1] + + def _onThisLine(span): + start, end = span + startExtents = list(text.getRangeExtents(start, start + 1, 0)) + endExtents = list(text.getRangeExtents(end - 1, end, 0)) + delta = max(startExtents[3], endExtents[3]) + if not self.extentsAreOnSameLine(startExtents, endExtents, delta): + tokens = ["FAIL: Start", startExtents, "and end", endExtents, + "of '", allText[start:end], "' not on same line"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + startExtents = endExtents + + return self.extentsAreOnSameLine(extents, startExtents) + + spans = [] + charCount = text.characterCount + if boundary == Atspi.TextBoundaryType.SENTENCE_START: + spans = [m.span() for m in re.finditer( + r"\S*[^\.\?\!]+((? 0 and self.treatAsEndOfLine(obj, offset): + extents = self.getExtents(obj, offset - 1, offset) + else: + extents = self.getExtents(obj, offset, offset + 1) + + if self.isInlineListDescendant(obj): + container = self.listForInlineListDescendant(obj) + if container: + extents = self.getExtents(container, 0, 1) + + objBanner = AXObject.find_ancestor(obj, self.isLandmarkBanner) + + def _include(x): + if x in objects: + return False + + xObj, xStart, xEnd, xString = x + if xStart == xEnd: + return False + + xExtents = self.getExtents(xObj, xStart, xStart + 1) + + if obj != xObj: + if self.isLandmark(obj) and self.isLandmark(xObj): + return False + if self.isLink(obj) and self.isLink(xObj): + xObjBanner = AXObject.find_ancestor(xObj, self.isLandmarkBanner) + if (objBanner or xObjBanner) and objBanner != xObjBanner: + return False + if abs(extents[0] - xExtents[0]) <= 1 and abs(extents[1] - xExtents[1]) <= 1: + # This happens with dynamic skip links such as found on Wikipedia. + return False + elif self.isBlockListDescendant(obj) != self.isBlockListDescendant(xObj): + return False + elif AXUtilities.is_tree_related(obj) and AXUtilities.is_tree_related(xObj): + return False + elif AXUtilities.is_heading(obj) and self.hasNoSize(obj): + return False + elif AXUtilities.is_heading(xObj) and self.hasNoSize(xObj): + return False + + if self.isMathTopLevel(xObj) or self.isMath(obj): + onSameLine = self.extentsAreOnSameLine(extents, xExtents, extents[3]) + elif self.isTextSubscriptOrSuperscript(xObj): + onSameLine = self.extentsAreOnSameLine(extents, xExtents, xExtents[3]) + else: + onSameLine = self.extentsAreOnSameLine(extents, xExtents) + return onSameLine + + boundary = Atspi.TextBoundaryType.LINE_START + objects = self._getContentsForObj(obj, offset, boundary) + if not layoutMode: + if useCache: + self._currentLineContents = objects + + self._debugContentsInfo(obj, offset, objects, "Line (not layout mode)") + return objects + + firstObj, firstStart, firstEnd, firstString = objects[0] + if (extents[2] == 0 and extents[3] == 0) or self.isMath(firstObj): + extents = self.getExtents(firstObj, firstStart, firstEnd) + + lastObj, lastStart, lastEnd, lastString = objects[-1] + if self.isMathTopLevel(lastObj): + lastObj, lastEnd = self.lastContext(lastObj) + lastEnd += 1 + + document = self.getDocumentForObject(obj) + prevObj, pOffset = self.findPreviousCaretInOrder(firstObj, firstStart) + nextObj, nOffset = self.findNextCaretInOrder(lastObj, lastEnd - 1) + + # Check for things on the same line to the left of this object. + prevStartTime = time.time() + while prevObj and self.getDocumentForObject(prevObj) == document: + text = self.queryNonEmptyText(prevObj) + if text and text.getText(pOffset, pOffset + 1) in [" ", "\xa0"]: + prevObj, pOffset = self.findPreviousCaretInOrder(prevObj, pOffset) + + if text and text.getText(pOffset, pOffset + 1) == "\n" and firstObj == prevObj: + break + + onLeft = self._getContentsForObj(prevObj, pOffset, boundary) + onLeft = list(filter(_include, onLeft)) + if not onLeft: + break + + if self._contentIsSubsetOf(objects[0], onLeft[-1]): + objects.pop(0) + + objects[0:0] = onLeft + firstObj, firstStart = objects[0][0], objects[0][1] + prevObj, pOffset = self.findPreviousCaretInOrder(firstObj, firstStart) + + prevEndTime = time.time() + msg = f"INFO: Time to get line contents on left: {prevEndTime - prevStartTime:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # Check for things on the same line to the right of this object. + nextStartTime = time.time() + while nextObj and self.getDocumentForObject(nextObj) == document: + text = self.queryNonEmptyText(nextObj) + if text and text.getText(nOffset, nOffset + 1) in [" ", "\xa0"]: + nextObj, nOffset = self.findNextCaretInOrder(nextObj, nOffset) + + if text and text.getText(nOffset, nOffset + 1) == "\n" and lastObj == nextObj: + break + + onRight = self._getContentsForObj(nextObj, nOffset, boundary) + if onRight and self._contentIsSubsetOf(objects[0], onRight[-1]): + onRight = onRight[0:-1] + + onRight = list(filter(_include, onRight)) + if not onRight: + break + + objects.extend(onRight) + lastObj, lastEnd = objects[-1][0], objects[-1][2] + if self.isMathTopLevel(lastObj): + lastObj, lastEnd = self.lastContext(lastObj) + lastEnd += 1 + + nextObj, nOffset = self.findNextCaretInOrder(lastObj, lastEnd - 1) + + nextEndTime = time.time() + msg = f"INFO: Time to get line contents on right: {nextEndTime - nextStartTime:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + firstObj, firstStart, firstEnd, firstString = objects[0] + if firstString == "\n" and len(objects) > 1: + objects.pop(0) + + if useCache: + self._currentLineContents = objects + + msg = f"INFO: Time to get line contents: {time.time() - startTime:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self._debugContentsInfo(obj, offset, objects, "Line (layout mode)") + + self._canHaveCaretContextDecision = {} + return objects + + def getPreviousLineContents(self, obj=None, offset=-1, layoutMode=None, useCache=True): + if obj is None: + obj, offset = self.getCaretContext() + + tokens = ["WEB: Current context is: ", obj, ", ", offset, + "(focus: ", cthulhu_state.locusOfFocus, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if obj and self.isZombie(obj): + tokens = ["WEB: Current context obj", obj, "is zombie. Clearing cache."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.clearCachedObjects() + + obj, offset = self.getCaretContext() + tokens = ["WEB: Now Current context is: ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + line = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + if not (line and line[0]): + return [] + + firstObj, firstOffset = line[0][0], line[0][1] + tokens = ["WEB: First context on line is: ", firstObj, ", ", firstOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + skipSpace = not self.elementIsPreformattedText(firstObj) + obj, offset = self.previousContext(firstObj, firstOffset, skipSpace) + if not obj and firstObj: + tokens = ["WEB: Previous context is: ", obj, ", ", offset, ". Trying again."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.clearCachedObjects() + obj, offset = self.previousContext(firstObj, firstOffset, skipSpace) + + tokens = ["WEB: Previous context is: ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + contents = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + if not contents: + tokens = ["WEB: Could not get line contents for ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + if line == contents: + obj, offset = self.previousContext(obj, offset, True) + tokens = ["WEB: Got same line. Trying again with ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + + if line == contents: + start, end = self.getHyperlinkRange(obj) + parent = AXObject.get_parent(obj) + tokens = ["WEB: Got same line. ", obj, "has range in", parent, "of", start, "-", end] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if start >= 0: + obj, offset = self.previousContext(parent, start, True) + tokens = ["WEB: Trying again with", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + + return contents + + def getNextLineContents(self, obj=None, offset=-1, layoutMode=None, useCache=True): + if obj is None: + obj, offset = self.getCaretContext() + + tokens = ["WEB: Current context is: ", obj, ", ", offset, + "(focus: ", cthulhu_state.locusOfFocus, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if obj and self.isZombie(obj): + tokens = ["WEB: Current context obj", obj, "is zombie. Clearing cache."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.clearCachedObjects() + + obj, offset = self.getCaretContext() + tokens = ["WEB: Now Current context is: ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + line = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + if not (line and line[0]): + return [] + + lastObj, lastOffset = line[-1][0], line[-1][2] - 1 + math = self.getMathAncestor(lastObj) + if math: + lastObj, lastOffset = self.lastContext(math) + + tokens = ["WEB: Last context on line is: ", lastObj, ", ", lastOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + skipSpace = not self.elementIsPreformattedText(lastObj) + obj, offset = self.nextContext(lastObj, lastOffset, skipSpace) + if not obj and lastObj: + tokens = ["WEB: Next context is: ", obj, ", ", offset, ". Trying again."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.clearCachedObjects() + obj, offset = self.nextContext(lastObj, lastOffset, skipSpace) + + tokens = ["WEB: Next context is: ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + contents = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + if line == contents: + obj, offset = self.nextContext(obj, offset, True) + tokens = ["WEB: Got same line. Trying again with ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + + if line == contents: + start, end = self.getHyperlinkRange(obj) + parent = AXObject.get_parent(obj) + tokens = ["WEB: Got same line. ", obj, "has range in", parent, "of", start, "-", end] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if end >= 0: + obj, offset = self.nextContext(parent, end, True) + tokens = ["WEB: Trying again with", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + contents = self.getLineContentsAtOffset(obj, offset, layoutMode, useCache) + + if not contents: + tokens = ["WEB: Could not get line contents for ", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + return contents + + def updateCachedTextSelection(self, obj): + if not self.inDocumentContent(obj): + super().updateCachedTextSelection(obj) + return + + if self.hasPresentableText(obj): + super().updateCachedTextSelection(obj) + + def _findSelectionBoundaryObject(self, root, findStart=True): + try: + text = root.queryText() + except Exception: + tokens = ["ERROR: Exception querying text for", root] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return None + + if not text.getNSelections(): + return None + + start, end = text.getSelection(0) + string = text.getText(start, end) + if not string: + return None + + if findStart and not string.startswith(self.EMBEDDED_OBJECT_CHARACTER): + return root + + if not findStart and not string.endswith(self.EMBEDDED_OBJECT_CHARACTER): + return root + + indices = list(range(AXObject.get_child_count(root))) + if not findStart: + indices.reverse() + + for i in indices: + result = self._findSelectionBoundaryObject(root[i], findStart) + if result: + return result + + return None + + def _getSelectionAnchorAndFocus(self, root): + obj1 = self._findSelectionBoundaryObject(root, True) + obj2 = self._findSelectionBoundaryObject(root, False) + return obj1, obj2 + + def _getSubtree(self, startObj, endObj): + if not (startObj and endObj): + return [] + + if AXObject.is_dead(startObj): + msg = "INFO: Cannot get subtree: Start object is dead." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return [] + + def _include(x): + return x is not None + + def _exclude(x): + return self.isStaticTextLeaf(x) + + subtree = [] + startObjParent = AXObject.get_parent(startObj) + for i in range(AXObject.get_index_in_parent(startObj), + AXObject.get_child_count(startObjParent)): + child = AXObject.get_child(startObjParent, i) + if self.isStaticTextLeaf(child): + continue + subtree.append(child) + subtree.extend(self.findAllDescendants(child, _include, _exclude)) + if endObj in subtree: + break + + if endObj == startObj: + return subtree + + if endObj not in subtree: + subtree.append(endObj) + subtree.extend(self.findAllDescendants(endObj, _include, _exclude)) + + endObjParent = AXObject.get_parent(endObj) + endObjIndex = AXObject.get_index_in_parent(endObj) + lastObj = AXObject.get_child(endObjParent, endObjIndex + 1) or endObj + + try: + endIndex = subtree.index(lastObj) + except ValueError: + pass + else: + if lastObj == endObj: + endIndex += 1 + subtree = subtree[:endIndex] + + return subtree + + def handleTextSelectionChange(self, obj, speakMessage=True): + if not self.inDocumentContent(obj): + return super().handleTextSelectionChange(obj) + + oldStart, oldEnd = \ + self._script.pointOfReference.get('selectionAnchorAndFocus', (None, None)) + start, end = self._getSelectionAnchorAndFocus(obj) + self._script.pointOfReference['selectionAnchorAndFocus'] = (start, end) + + def _cmp(obj1, obj2): + return self.pathComparison(AXObject.get_path(obj1), AXObject.get_path(obj2)) + + oldSubtree = self._getSubtree(oldStart, oldEnd) + if start == oldStart and end == oldEnd: + descendants = oldSubtree + else: + newSubtree = self._getSubtree(start, end) + descendants = sorted(set(oldSubtree).union(newSubtree), key=functools.cmp_to_key(_cmp)) + + if not descendants: + return False + + for descendant in descendants: + if descendant not in (oldStart, oldEnd, start, end) \ + and AXObject.find_ancestor(descendant, lambda x: x in descendants): + super().updateCachedTextSelection(descendant) + else: + super().handleTextSelectionChange(descendant, speakMessage) + + return True + + def inPDFViewer(self, obj=None): + uri = self.documentFrameURI() + return uri.lower().endswith(".pdf") + + def inTopLevelWebApp(self, obj=None): + if not obj: + obj = cthulhu_state.locusOfFocus + + rv = self._inTopLevelWebApp.get(hash(obj)) + if rv is not None: + return rv + + document = self.getDocumentForObject(obj) + if not document and self.isDocument(obj): + document = obj + + rv = self.isTopLevelWebApp(document) + self._inTopLevelWebApp[hash(obj)] = rv + return rv + + def isTopLevelWebApp(self, obj): + if AXUtilities.is_embedded(obj) \ + and not self.getDocumentForObject(AXObject.get_parent(obj)): + uri = self.documentFrameURI() + rv = bool(uri and uri.startswith("http")) + tokens = ["WEB:", obj, "is top-level web application:", rv, "(URI:", uri, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + return False + + def forceBrowseModeForWebAppDescendant(self, obj): + if not self.isWebAppDescendant(obj): + return False + + if AXUtilities.is_tool_tip(obj): + return AXUtilities.is_focused(obj) + + if AXUtilities.is_document_web(obj): + return not self.isFocusModeWidget(obj) + + return False + + def isFocusModeWidget(self, obj): + if AXUtilities.is_editable(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's editable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if AXUtilities.is_expandable(obj) and AXUtilities.is_focusable(obj) \ + and not AXUtilities.is_link(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's expandable and focusable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + alwaysFocusModeRoles = [Atspi.Role.COMBO_BOX, + Atspi.Role.ENTRY, + Atspi.Role.LIST_BOX, + Atspi.Role.MENU, + Atspi.Role.MENU_ITEM, + Atspi.Role.CHECK_MENU_ITEM, + Atspi.Role.RADIO_MENU_ITEM, + Atspi.Role.PAGE_TAB, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.PROGRESS_BAR, + Atspi.Role.SLIDER, + Atspi.Role.SPIN_BUTTON, + Atspi.Role.TOOL_BAR, + Atspi.Role.TREE_ITEM, + Atspi.Role.TREE_TABLE, + Atspi.Role.TREE] + + role = AXObject.get_role(obj) + if role in alwaysFocusModeRoles: + tokens = ["WEB:", obj, "is focus mode widget due to its role"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if role in [Atspi.Role.TABLE_CELL, Atspi.Role.TABLE] \ + and self.isLayoutOnly(self.getTable(obj)): + tokens = ["WEB:", obj, "is not focus mode widget because it's layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if AXUtilities.is_list_item(obj): + rv = AXObject.find_ancestor(obj, AXUtilities.is_list_box) + if rv: + tokens = ["WEB:", obj, "is focus mode widget because it's a listbox descendant"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + if self.isButtonWithPopup(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's a button with popup"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + focusModeRoles = [Atspi.Role.EMBEDDED, + Atspi.Role.TABLE_CELL, + Atspi.Role.TABLE] + + if role in focusModeRoles \ + and not self.isTextBlockElement(obj) \ + and not self.hasNameAndActionAndNoUsefulChildren(obj) \ + and not self.inPDFViewer(obj): + tokens = ["WEB:", obj, "is focus mode widget based on presumed functionality"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self.isGridDescendant(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's a grid descendant"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self.isMenuDescendant(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's a menu descendant"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self.isToolBarDescendant(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's a toolbar descendant"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + if self.isContentEditableWithEmbeddedObjects(obj): + tokens = ["WEB:", obj, "is focus mode widget because it's content editable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def _textBlockElementRoles(self): + roles = [Atspi.Role.ARTICLE, + Atspi.Role.CAPTION, + Atspi.Role.COLUMN_HEADER, + Atspi.Role.COMMENT, + Atspi.Role.DEFINITION, + Atspi.Role.DESCRIPTION_LIST, + Atspi.Role.DESCRIPTION_TERM, + Atspi.Role.DESCRIPTION_VALUE, + Atspi.Role.DOCUMENT_FRAME, + Atspi.Role.DOCUMENT_WEB, + Atspi.Role.FOOTER, + Atspi.Role.FORM, + Atspi.Role.HEADING, + Atspi.Role.LIST, + Atspi.Role.LIST_ITEM, + Atspi.Role.PARAGRAPH, + Atspi.Role.ROW_HEADER, + Atspi.Role.SECTION, + Atspi.Role.STATIC, + Atspi.Role.TEXT, + Atspi.Role.TABLE_CELL] + + # Remove this check when we bump dependencies to 2.34 + try: + roles.append(Atspi.Role.CONTENT_DELETION) + roles.append(Atspi.Role.CONTENT_INSERTION) + except Exception: + pass + + # Remove this check when we bump dependencies to 2.36 + try: + roles.append(Atspi.Role.MARK) + roles.append(Atspi.Role.SUGGESTION) + except Exception: + pass + + return roles + + def mnemonicShortcutAccelerator(self, obj): + attrs = self.objectAttributes(obj) + keys = map(lambda x: x.replace("+", " "), attrs.get("keyshortcuts", "").split(" ")) + keys = map(lambda x: x.replace(" ", "+"), map(self.labelFromKeySequence, keys)) + rv = ["", " ".join(keys), ""] + if list(filter(lambda x: x, rv)): + return rv + + return super().mnemonicShortcutAccelerator(obj) + + def unrelatedLabels(self, root, onlyShowing=True, minimumWords=3): + if not (root and self.inDocumentContent(root)): + return super().unrelatedLabels(root, onlyShowing, minimumWords) + + return [] + + def isFocusableWithMathChild(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isFocusableWithMathChild.get(hash(obj)) + if rv is not None: + return rv + + rv = False + if AXUtilities.is_focusable(obj) \ + and not self.isDocument(obj): + for child in AXObject.iter_children(obj, self.isMathTopLevel): + rv = True + break + + self._isFocusableWithMathChild[hash(obj)] = rv + return rv + + def isFocusedWithMathChild(self, obj): + if not self.isFocusableWithMathChild(obj): + return False + return AXUtilities.is_focused(obj) + + def isTextBlockElement(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isTextBlockElement.get(hash(obj)) + if rv is not None: + return rv + + role = AXObject.get_role(obj) + textBlockElements = self._textBlockElementRoles() + if role not in textBlockElements: + rv = False + elif not AXObject.supports_text(obj): + rv = False + elif AXUtilities.is_editable(obj): + rv = False + elif self.isGridCell(obj): + rv = False + elif AXUtilities.is_document(obj): + rv = True + elif self.isCustomImage(obj): + rv = False + elif not AXUtilities.is_focusable(obj): + rv = not self.hasNameAndActionAndNoUsefulChildren(obj) + else: + rv = False + + self._isTextBlockElement[hash(obj)] = rv + return rv + + def _advanceCaretInEmptyObject(self, obj): + if AXUtilities.is_table_cell(obj) and not self.queryNonEmptyText(obj): + return not self._script._lastCommandWasStructNav + + return True + + def textAtPoint(self, obj, x, y, coordType=None, boundary=None): + if coordType is None: + coordType = Atspi.CoordType.SCREEN + + if boundary is None: + boundary = Atspi.TextBoundaryType.LINE_START + + string, start, end = super().textAtPoint(obj, x, y, coordType, boundary) + if string == self.EMBEDDED_OBJECT_CHARACTER: + child = self.findChildAtOffset(obj, start) + if child: + return self.textAtPoint(child, x, y, coordType, boundary) + + return string, start, end + + def _treatAlertsAsDialogs(self): + return False + + def treatAsDiv(self, obj, offset=None): + if not (obj and self.inDocumentContent(obj)): + return False + + if self.isDescriptionList(obj): + return False + + if AXUtilities.is_list(obj) and offset is not None: + string = self.substring(obj, offset, offset + 1) + if string and string != self.EMBEDDED_OBJECT_CHARACTER: + return True + + childCount = AXObject.get_child_count(obj) + if AXUtilities.is_panel(obj) and not childCount: + return True + + rv = self._treatAsDiv.get(hash(obj)) + if rv is not None: + return rv + + validRoles = self._validChildRoles.get(AXObject.get_role(obj)) + if validRoles: + if not childCount: + rv = True + else: + def pred1(x): + return x is not None and AXObject.get_role(x) not in validRoles + + rv = bool([x for x in AXObject.iter_children(obj, pred1)]) + + if not rv: + parent = AXObject.get_parent(obj) + validRoles = self._validChildRoles.get(parent) + if validRoles: + def pred2(x): + return x is not None and AXObject.get_role(x) not in validRoles + + rv = bool([x for x in AXObject.iter_children(parent, pred2)]) + + self._treatAsDiv[hash(obj)] = rv + return rv + + def isAriaAlert(self, obj): + return 'alert' in self._getXMLRoles(obj) + + def isBlockquote(self, obj): + if super().isBlockquote(obj): + return True + + return self._getTag(obj) == 'blockquote' + + def isComment(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isComment(obj) + + if AXUtilities.is_comment(obj): + return True + + return 'comment' in self._getXMLRoles(obj) + + def isContentDeletion(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isContentDeletion(obj) + + if AXUtilities.is_content_deletion(obj): + return True + + return 'deletion' in self._getXMLRoles(obj) or 'del' == self._getTag(obj) + + def isContentError(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isContentError(obj) + + if AXObject.get_role(obj) not in self._textBlockElementRoles(): + return False + + return AXUtilities.is_invalid_entry(obj) + + def isContentInsertion(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isContentInsertion(obj) + + if AXUtilities.is_content_insertion(obj): + return True + + return 'insertion' in self._getXMLRoles(obj) or 'ins' == self._getTag(obj) + + def isContentMarked(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isContentMarked(obj) + + if AXUtilities.is_mark(obj): + return True + + return 'mark' in self._getXMLRoles(obj) or 'mark' == self._getTag(obj) + + def isContentSuggestion(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isContentSuggestion(obj) + + if AXUtilities.is_suggestion(obj): + return True + + return 'suggestion' in self._getXMLRoles(obj) + + def isCustomElement(self, obj): + tag = self._getTag(obj) + return tag and '-' in tag + + def isInlineIframe(self, obj): + if not AXUtilities.is_internal_frame(obj): + return False + + displayStyle = self._getDisplayStyle(obj) + if "inline" not in displayStyle: + return False + + return self.getDocumentForObject(obj) is not None + + def isInlineIframeDescendant(self, obj): + if not obj: + return False + + rv = self._isInlineIframeDescendant.get(hash(obj)) + if rv is not None: + return rv + + ancestor = AXObject.find_ancestor(obj, self.isInlineIframe) + rv = ancestor is not None + self._isInlineIframeDescendant[hash(obj)] = rv + return rv + + def isInlineSuggestion(self, obj): + if not self.isContentSuggestion(obj): + return False + + displayStyle = self._getDisplayStyle(obj) + return "inline" in displayStyle + + def isSVG(self, obj): + return 'svg' == self._getTag(obj) + + def isTextField(self, obj): + if AXUtilities.is_text_input(obj): + return True + + if AXUtilities.is_combo_box(obj): + return self.isEditableComboBox(obj) + + return False + + def isFirstItemInInlineContentSuggestion(self, obj): + suggestion = AXObject.find_ancestor(obj, self.isInlineSuggestion) + if not (suggestion and AXObject.get_child_count(suggestion)): + return False + + return suggestion[0] == obj + + def isLastItemInInlineContentSuggestion(self, obj): + suggestion = AXObject.find_ancestor(obj, self.isInlineSuggestion) + if not (suggestion and AXObject.get_child_count(suggestion)): + return False + + return suggestion[-1] == obj + + def speakMathSymbolNames(self, obj=None): + obj = obj or cthulhu_state.locusOfFocus + return self.isMath(obj) + + def isInMath(self): + return self.isMath(cthulhu_state.locusOfFocus) + + def isMath(self, obj): + tag = self._getTag(obj) + rv = tag in ['math', + 'maction', + 'maligngroup', + 'malignmark', + 'menclose', + 'merror', + 'mfenced', + 'mfrac', + 'mglyph', + 'mi', + 'mlabeledtr', + 'mlongdiv', + 'mmultiscripts', + 'mn', + 'mo', + 'mover', + 'mpadded', + 'mphantom', + 'mprescripts', + 'mroot', + 'mrow', + 'ms', + 'mscarries', + 'mscarry', + 'msgroup', + 'msline', + 'mspace', + 'msqrt', + 'msrow', + 'mstack', + 'mstyle', + 'msub', + 'msup', + 'msubsup', + 'mtable', + 'mtd', + 'mtext', + 'mtr', + 'munder', + 'munderover'] + + return rv + + def isNoneElement(self, obj): + return self._getTag(obj) == 'none' + + def isMathLayoutOnly(self, obj): + return self._getTag(obj) in ['mrow', 'mstyle', 'merror', 'mpadded'] + + def isMathMultiline(self, obj): + return self._getTag(obj) in ['mtable', 'mstack', 'mlongdiv'] + + def isMathEnclose(self, obj): + return self._getTag(obj) == 'menclose' + + def isMathFenced(self, obj): + return self._getTag(obj) == 'mfenced' + + def isMathFractionWithoutBar(self, obj): + if not AXUtilities.is_math_fraction(obj): + return False + + attrs = self.objectAttributes(obj) + linethickness = attrs.get('linethickness') + if not linethickness: + return False + + for char in linethickness: + if char.isnumeric() and char != '0': + return False + + return True + + def isMathPhantom(self, obj): + return self._getTag(obj) == 'mphantom' + + def isMathMultiScript(self, obj): + return self._getTag(obj) == 'mmultiscripts' + + def _isMathPrePostScriptSeparator(self, obj): + return self._getTag(obj) == 'mprescripts' + + def isMathSubOrSuperScript(self, obj): + return self._getTag(obj) in ['msub', 'msup', 'msubsup'] + + def isMathTable(self, obj): + return self._getTag(obj) == 'mtable' + + def isMathTableRow(self, obj): + return self._getTag(obj) in ['mtr', 'mlabeledtr'] + + def isMathTableCell(self, obj): + return self._getTag(obj) == 'mtd' + + def isMathUnderOrOverScript(self, obj): + return self._getTag(obj) in ['mover', 'munder', 'munderover'] + + def _isMathSubElement(self, obj): + return self._getTag(obj) == 'msub' + + def _isMathSupElement(self, obj): + return self._getTag(obj) == 'msup' + + def _isMathSubsupElement(self, obj): + return self._getTag(obj) == 'msubsup' + + def _isMathUnderElement(self, obj): + return self._getTag(obj) == 'munder' + + def _isMathOverElement(self, obj): + return self._getTag(obj) == 'mover' + + def _isMathUnderOverElement(self, obj): + return self._getTag(obj) == 'munderover' + + def isMathSquareRoot(self, obj): + return self._getTag(obj) == 'msqrt' + + def isMathToken(self, obj): + return self._getTag(obj) in ['mi', 'mn', 'mo', 'mtext', 'ms', 'mspace'] + + def isMathTopLevel(self, obj): + return AXUtilities.is_math(obj) + + def getMathAncestor(self, obj): + if not self.isMath(obj): + return None + + if self.isMathTopLevel(obj): + return obj + + return AXObject.find_ancestor(obj, self.isMathTopLevel) + + def getMathDenominator(self, obj): + return AXObject.get_child(obj, 1) + + def getMathNumerator(self, obj): + return AXObject.get_child(obj, 0) + + def getMathRootBase(self, obj): + if self.isMathSquareRoot(obj): + return obj + + return AXObject.get_child(obj, 0) + + def getMathRootIndex(self, obj): + return AXObject.get_child(obj, 1) + + def getMathScriptBase(self, obj): + if self.isMathSubOrSuperScript(obj) \ + or self.isMathUnderOrOverScript(obj) \ + or self.isMathMultiScript(obj): + return AXObject.get_child(obj, 0) + + return None + + def getMathScriptSubscript(self, obj): + if self._isMathSubElement(obj) or self._isMathSubsupElement(obj): + return AXObject.get_child(obj, 1) + + return None + + def getMathScriptSuperscript(self, obj): + if self._isMathSupElement(obj): + return AXObject.get_child(obj, 1) + + if self._isMathSubsupElement(obj): + return AXObject.get_child(obj, 2) + + return None + + def getMathScriptUnderscript(self, obj): + if self._isMathUnderElement(obj) or self._isMathUnderOverElement(obj): + return AXObject.get_child(obj, 1) + + return None + + def getMathScriptOverscript(self, obj): + if self._isMathOverElement(obj): + return AXObject.get_child(obj, 1) + + if self._isMathUnderOverElement(obj): + return AXObject.get_child(obj, 2) + + return None + + def _getMathPrePostScriptSeparator(self, obj): + for child in AXObject.iter_children(obj): + if self._isMathPrePostScriptSeparator(child): + return child + + return None + + def getMathPrescripts(self, obj): + separator = self._getMathPrePostScriptSeparator(obj) + if not separator: + return [] + + children = [] + child = AXObject.get_next_sibling(separator) + while child: + children.append(child) + child = AXObject.get_next_sibling(child) + + return children + + def getMathPostscripts(self, obj): + separator = self._getMathPrePostScriptSeparator(obj) + children = [] + child = AXObject.get_child(obj, 1) + while child and child != separator: + children.append(child) + child = AXObject.get_next_sibling(child) + + return children + + def getMathEnclosures(self, obj): + if not self.isMathEnclose(obj): + return [] + + attrs = self.objectAttributes(obj) + return attrs.get('notation', 'longdiv').split() + + def getMathFencedSeparators(self, obj): + if not self.isMathFenced(obj): + return [''] + + attrs = self.objectAttributes(obj) + return list(attrs.get('separators', ',')) + + def getMathFences(self, obj): + if not self.isMathFenced(obj): + return ['', ''] + + attrs = self.objectAttributes(obj) + return [attrs.get('open', '('), attrs.get('close', ')')] + + def getMathNestingLevel(self, obj, test=None): + rv = self._mathNestingLevel.get(hash(obj)) + if rv is not None: + return rv + + def pred(x): + if test is not None: + return test(x) + return self._getTag(x) == self._getTag(obj) + + rv = -1 + ancestor = obj + while ancestor: + ancestor = AXObject.find_ancestor(ancestor, pred) + rv += 1 + + self._mathNestingLevel[hash(obj)] = rv + return rv + + def filterContentsForPresentation(self, contents, inferLabels=False): + def _include(x): + obj, start, end, string = x + if not obj or AXObject.is_dead(obj): + return False + + rv = self._shouldFilter.get(hash(obj)) + if rv is not None: + return rv + + displayedText = string or AXObject.get_name(obj) + rv = True + if ((self.isTextBlockElement(obj) or self.isLink(obj)) and not displayedText) \ + or (self.isContentEditableWithEmbeddedObjects(obj) and not string.strip()) \ + or self.isEmptyAnchor(obj) \ + or (self.hasNoSize(obj) and not displayedText) \ + or self.isHidden(obj) \ + or self.isOffScreenLabel(obj) \ + or self.isUselessImage(obj) \ + or self.isErrorForContents(obj, contents) \ + or self.isLabellingContents(obj, contents): + rv = False + elif AXUtilities.is_table_row(obj): + rv = self.hasExplicitName(obj) + else: + widget = self.isInferredLabelForContents(x, contents) + alwaysFilter = [Atspi.Role.RADIO_BUTTON, Atspi.Role.CHECK_BOX] + if widget and (inferLabels or AXObject.get_role(widget) in alwaysFilter): + rv = False + + self._shouldFilter[hash(obj)] = rv + return rv + + if len(contents) == 1: + return contents + + rv = list(filter(_include, contents)) + self._shouldFilter = {} + return rv + + def needsSeparator(self, lastChar, nextChar): + if lastChar.isspace() or nextChar.isspace(): + return False + + openingPunctuation = ["(", "[", "{", "<"] + closingPunctuation = [".", "?", "!", ":", ",", ";", ")", "]", "}", ">"] + if lastChar in closingPunctuation or nextChar in openingPunctuation: + return True + if lastChar in openingPunctuation or nextChar in closingPunctuation: + return False + + return lastChar.isalnum() + + def supportsSelectionAndTable(self, obj): + return AXObject.supports_table(obj) and AXObject.supports_selection(obj) + + def hasGridDescendant(self, obj): + if not obj: + return False + + rv = self._hasGridDescendant.get(hash(obj)) + if rv is not None: + return rv + + if not AXObject.get_child_count(obj): + rv = False + else: + document = self.documentFrame(obj) + if obj != document: + document_has_grids = self.hasGridDescendant(document) + if not document_has_grids: + rv = False + + if rv is None: + grids = AXUtilities.find_all_grids(obj) + rv = bool(grids) + + self._hasGridDescendant[hash(obj)] = rv + return rv + + def isGridDescendant(self, obj): + if not obj: + return False + + rv = self._isGridDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, self.supportsSelectionAndTable) is not None + self._isGridDescendant[hash(obj)] = rv + return rv + + def isSorted(self, obj): + attrs = self.objectAttributes(obj, False) + return attrs.get("sort") not in ("none", None) + + def isAscending(self, obj): + attrs = self.objectAttributes(obj, False) + return attrs.get("sort") == "ascending" + + def isDescending(self, obj): + attrs = self.objectAttributes(obj, False) + return attrs.get("sort") == "descending" + + def _rowAndColumnIndices(self, obj): + rowindex = colindex = None + + attrs = self.objectAttributes(obj) + rowindex = attrs.get('rowindex') + colindex = attrs.get('colindex') + if rowindex is not None and colindex is not None: + return rowindex, colindex + + row = AXObject.find_ancestor(obj, AXUtilities.is_table_row) + if row is None: + return rowindex, colindex + + attrs = self.objectAttributes(row) + rowindex = attrs.get('rowindex', rowindex) + colindex = attrs.get('colindex', colindex) + return rowindex, colindex + + def isCellWithNameFromHeader(self, obj): + if not AXUtilities.is_table_cell(obj): + return False + + name = AXObject.get_name(obj) + if not name: + return False + + header = self.columnHeaderForCell(obj) + if header and AXObject.get_name(header) == name: + return True + + header = self.rowHeaderForCell(obj) + if header and AXObject.get_name(header) == name: + return True + + return False + + def labelForCellCoordinates(self, obj): + attrs = self.objectAttributes(obj) + + # The ARIA feature is still in the process of being discussed. + collabel = attrs.get('colindextext', attrs.get('coltext')) + rowlabel = attrs.get('rowindextext', attrs.get('rowtext')) + if collabel is not None and rowlabel is not None: + return f'{collabel}{rowlabel}' + + row = AXObject.find_ancestor(obj, AXUtilities.is_table_row) + if row is None: + return '' + + attrs = self.objectAttributes(row) + collabel = attrs.get('colindextext', attrs.get('coltext', collabel)) + rowlabel = attrs.get('rowindextext', attrs.get('rowtext', rowlabel)) + if collabel is not None and rowlabel is not None: + return f'{collabel}{rowlabel}' + + return '' + + def coordinatesForCell(self, obj, preferAttribute=True, findCellAncestor=False): + if not AXUtilities.is_table_cell_or_header(obj): + if not findCellAncestor: + return -1, -1 + + cell = AXObject.find_ancestor(obj, AXUtilities.is_table_cell_or_header) + return self.coordinatesForCell(cell, preferAttribute, False) + + if not preferAttribute: + return super().coordinatesForCell(obj, preferAttribute) + + rvRow = rvCol = None + rowindex, colindex = self._rowAndColumnIndices(obj) + if rowindex is None or colindex is None: + nativeRowindex, nativeColindex = super().coordinatesForCell(obj, False) + if rowindex is not None: + rvRow = int(rowindex) - 1 + else: + rvRow = nativeRowindex + if colindex is not None: + rvCol = int(colindex) - 1 + else: + rvCol = nativeColindex + + return rvRow, rvCol + + def setSizeUnknown(self, obj): + if super().setSizeUnknown(obj): + return True + + attrs = self.objectAttributes(obj) + return attrs.get('setsize') == '-1' + + def rowOrColumnCountUnknown(self, obj): + if super().rowOrColumnCountUnknown(obj): + return True + + attrs = self.objectAttributes(obj) + return attrs.get('rowcount') == '-1' or attrs.get('colcount') == '-1' + + def rowAndColumnCount(self, obj, preferAttribute=True): + rows, cols = super().rowAndColumnCount(obj) + if not preferAttribute: + return rows, cols + + attrs = self.objectAttributes(obj) + rows = attrs.get('rowcount', rows) + cols = attrs.get('colcount', cols) + return int(rows), int(cols) + + def shouldReadFullRow(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().shouldReadFullRow(obj) + + if not super().shouldReadFullRow(obj): + return False + + if self.isGridDescendant(obj): + return not self._script.inFocusMode() + + if self.lastInputEventWasLineNav(): + return False + + if self.lastInputEventWasMouseButton(): + return False + + return True + + def isEntryDescendant(self, obj): + if not obj: + return False + + rv = self._isEntryDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, AXUtilities.is_entry) is not None + self._isEntryDescendant[hash(obj)] = rv + return rv + + def isLabelDescendant(self, obj): + if not obj: + return False + + rv = self._isLabelDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, AXUtilities.is_label_or_caption) is not None + self._isLabelDescendant[hash(obj)] = rv + return rv + + def isMenuInCollapsedSelectElement(self, obj): + return False + + def isMenuDescendant(self, obj): + if not obj: + return False + + rv = self._isMenuDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, AXUtilities.is_menu) is not None + self._isMenuDescendant[hash(obj)] = rv + return rv + + def isModalDialogDescendant(self, obj): + if not obj: + return False + + rv = self._isModalDialogDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = super().isModalDialogDescendant(obj) + self._isModalDialogDescendant[hash(obj)] = rv + return rv + + def isNavigableToolTipDescendant(self, obj): + if not obj: + return False + + rv = self._isNavigableToolTipDescendant.get(hash(obj)) + if rv is not None: + return rv + + if AXUtilities.is_tool_tip(obj): + ancestor = obj + else: + ancestor = AXObject.find_ancestor(obj, AXUtilities.is_tool_tip) + rv = ancestor and not self.isNonNavigablePopup(ancestor) + self._isNavigableToolTipDescendant[hash(obj)] = rv + return rv + + def isTime(self, obj): + return 'time' in self._getXMLRoles(obj) or 'time' == self._getTag(obj) + + def isToolBarDescendant(self, obj): + if not obj: + return False + + rv = self._isToolBarDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, AXUtilities.is_tool_bar) is not None + self._isToolBarDescendant[hash(obj)] = rv + return rv + + def isWebAppDescendant(self, obj): + if not obj: + return False + + rv = self._isWebAppDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, AXUtilities.is_embedded) is not None + self._isWebAppDescendant[hash(obj)] = rv + return rv + + def isLayoutOnly(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isLayoutOnly(obj) + + rv = self._isLayoutOnly.get(hash(obj)) + if rv is not None: + if rv: + tokens = ["WEB:", obj, "is deemed to be layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + if AXUtilities.is_list(obj): + rv = self.treatAsDiv(obj) + elif self.isDescriptionList(obj): + rv = False + elif self.isDescriptionListTerm(obj): + rv = False + elif self.isDescriptionListDescription(obj): + rv = False + elif self.isMath(obj): + rv = False + elif self.isLandmark(obj): + rv = False + elif self.isContentDeletion(obj): + rv = False + elif self.isContentInsertion(obj): + rv = False + elif self.isContentMarked(obj): + rv = False + elif self.isContentSuggestion(obj): + rv = False + elif self.isDPub(obj): + rv = False + elif self.isFeed(obj): + rv = False + elif self.isFigure(obj): + rv = False + elif self.isGrid(obj): + rv = False + elif AXUtilities.is_table_header(obj): + rv = False + elif AXUtilities.is_separator(obj): + rv = False + elif AXUtilities.is_panel(obj): + rv = not self.hasExplicitName(obj) + elif AXUtilities.is_table_row(obj) and not AXUtilities.is_expandable(obj): + rv = not self.hasExplicitName(obj) + elif self.isCustomImage(obj): + rv = False + else: + rv = super().isLayoutOnly(obj) + + if rv: + tokens = ["WEB:", obj, "is deemed to be layout only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._isLayoutOnly[hash(obj)] = rv + return rv + + def elementIsPreformattedText(self, obj): + if self._getTag(obj) in ["pre", "code"]: + return True + + if "code" in self._getXMLRoles(obj): + return True + + return False + + def elementLinesAreSingleWords(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + if self.elementIsPreformattedText(obj): + return False + + rv = self._elementLinesAreSingleWords.get(hash(obj)) + if rv is not None: + return rv + + text = self.queryNonEmptyText(obj) + if not text: + return False + + try: + nChars = text.characterCount + except Exception: + return False + + if not nChars: + return False + + # If we have a series of embedded object characters, there's a reasonable chance + # they'll look like the one-word-per-line CSSified text we're trying to detect. + # We don't want that false positive. By the same token, the one-word-per-line + # CSSified text we're trying to detect can have embedded object characters. So + # if we have more than 30% EOCs, don't use this workaround. (The 30% is based on + # testing with problematic text.) + eocs = re.findall(self.EMBEDDED_OBJECT_CHARACTER, text.getText(0, -1)) + if len(eocs)/nChars > 0.3: + return False + + AXObject.clear_cache(obj) + tokens = list(filter(lambda x: x, re.split(r"[\s\ufffc]", text.getText(0, -1)))) + + # Note: We cannot check for the editable-text interface, because Gecko + # seems to be exposing that for non-editable things. Thanks Gecko. + rv = not AXUtilities.is_editable(obj) and len(tokens) > 1 + if rv: + boundary = Atspi.TextBoundaryType.LINE_START + i = 0 + while i < nChars: + string, start, end = text.getTextAtOffset(i, boundary) + if len(string.split()) != 1: + rv = False + break + i = max(i+1, end) + + self._elementLinesAreSingleWords[hash(obj)] = rv + return rv + + def elementLinesAreSingleChars(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._elementLinesAreSingleChars.get(hash(obj)) + if rv is not None: + return rv + + text = self.queryNonEmptyText(obj) + if not text: + return False + + try: + nChars = text.characterCount + except Exception: + return False + + if not nChars: + return False + + # If we have a series of embedded object characters, there's a reasonable chance + # they'll look like the one-char-per-line CSSified text we're trying to detect. + # We don't want that false positive. By the same token, the one-char-per-line + # CSSified text we're trying to detect can have embedded object characters. So + # if we have more than 30% EOCs, don't use this workaround. (The 30% is based on + # testing with problematic text.) + eocs = re.findall(self.EMBEDDED_OBJECT_CHARACTER, text.getText(0, -1)) + if len(eocs)/nChars > 0.3: + return False + + AXObject.clear_cache(obj) + + # Note: We cannot check for the editable-text interface, because Gecko + # seems to be exposing that for non-editable things. Thanks Gecko. + rv = not AXUtilities.is_editable(obj) + if rv: + boundary = Atspi.TextBoundaryType.LINE_START + for i in range(nChars): + char = text.getText(i, i + 1) + if char.isspace() or char in ["\ufffc", "\ufffd"]: + continue + + string, start, end = text.getTextAtOffset(i, boundary) + if len(string.strip()) > 1: + rv = False + break + + self._elementLinesAreSingleChars[hash(obj)] = rv + return rv + + def labelIsAncestorOfLabelled(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._labelIsAncestorOfLabelled.get(hash(obj)) + if rv is not None: + return rv + + rv = False + for target in self.targetsForLabel(obj): + if AXObject.find_ancestor(target, lambda x: x == obj): + rv = True + break + + self._labelIsAncestorOfLabelled[hash(obj)] = rv + return rv + + def isOffScreenLabel(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isOffScreenLabel.get(hash(obj)) + if rv is not None: + return rv + + if self.labelIsAncestorOfLabelled(obj): + return False + + rv = False + targets = self.labelTargets(obj) + if targets: + try: + text = obj.queryText() + end = text.characterCount + except Exception: + end = 1 + x, y, width, height = self.getExtents(obj, 0, end) + if x < 0 or y < 0: + rv = True + + self._isOffScreenLabel[hash(obj)] = rv + return rv + + def isDetachedDocument(self, obj): + if AXUtilities.is_document(obj): + parent = AXObject.get_parent(obj) + if parent is None or self.isZombie(parent): + tokens = ["WEB:", obj, "is a detached document"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False + + def iframeForDetachedDocument(self, obj, root=None): + root = root or self.documentFrame() + for iframe in AXUtilities.find_all_internal_frames(root): + if AXObject.get_parent(obj) == iframe: + tokens = ["WEB: Returning", iframe, "as iframe parent of detached", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return iframe + + return None + + def _objectBoundsMightBeBogus(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super()._objectBoundsMightBeBogus(obj) + + if not AXUtilities.is_link(obj) or not AXObject.supports_text(obj): + return False + + text = obj.queryText() + start = list(text.getRangeExtents(0, 1, 0)) + end = list(text.getRangeExtents(text.characterCount - 1, text.characterCount, 0)) + if self.extentsAreOnSameLine(start, end): + return False + + if not self.hasPresentableText(AXObject.get_parent(obj)): + return False + + tokens = ["WEB: Objects bounds of", obj, "might be bogus"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def targetsForLabel(self, obj): + return AXObject.get_relation_targets(obj, Atspi.RelationType.LABEL_FOR) + + def labelTargets(self, obj): + if not (obj and self.inDocumentContent(obj)): + return [] + + rv = self._labelTargets.get(hash(obj)) + if rv is not None: + return rv + + rv = [hash(t) for t in self.targetsForLabel(obj)] + self._labelTargets[hash(obj)] = rv + return rv + + def isLinkAncestorOfImageInContents(self, link, contents): + if not self.isLink(link): + return False + + for obj, start, end, string in contents: + if not AXUtilities.is_image(obj): + continue + if AXObject.find_ancestor(obj, lambda x: x == link): + return True + + return False + + def isInferredLabelForContents(self, content, contents): + obj, start, end, string = content + objs = list(filter(self.shouldInferLabelFor, [x[0] for x in contents])) + if not objs: + return None + + for o in objs: + label, sources = self.inferLabelFor(o) + if obj in sources and label.strip() == string.strip(): + return o + + return None + + def isLabellingInteractiveElement(self, obj): + if self._labelTargets.get(hash(obj)) == []: + return False + + targets = self.targetsForLabel(obj) + for target in targets: + if AXUtilities.is_focusable(target): + return True + + return False + + def isLabellingContents(self, obj, contents=[]): + if self.isFocusModeWidget(obj): + return False + + targets = self.labelTargets(obj) + if not contents: + return bool(targets) or self.isLabelDescendant(obj) + + for acc, start, end, string in contents: + if hash(acc) in targets: + return True + + if not self.isTextBlockElement(obj): + return False + + if not self.isLabelDescendant(obj): + return False + + for acc, start, end, string in contents: + if not self.isLabelDescendant(acc) or self.isTextBlockElement(acc): + continue + + if AXUtilities.is_label_or_caption(self.commonAncestor(acc, obj)): + return True + + return False + + def isAnchor(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isAnchor.get(hash(obj)) + if rv is not None: + return rv + + rv = False + if AXUtilities.is_link(obj) \ + and not AXUtilities.is_focusable(obj) \ + and not AXObject.has_action(obj, "jump") \ + and not self._getXMLRoles(obj): + rv = True + + self._isAnchor[hash(obj)] = rv + return rv + + def isEmptyAnchor(self, obj): + if not self.isAnchor(obj): + return False + + return self.queryNonEmptyText(obj) is None + + def isEmptyToolTip(self, obj): + return AXUtilities.is_tool_tip(obj) and self.queryNonEmptyText(obj) is None + + def isBrowserUIAlert(self, obj): + if not AXUtilities.is_alert(obj): + return False + + if self.inDocumentContent(obj): + return False + + return True + + def isTopLevelBrowserUIAlert(self, obj): + if not self.isBrowserUIAlert(obj): + return False + + parent = AXObject.get_parent(obj) + while parent and self.isLayoutOnly(parent): + parent = AXObject.get_parent(parent) + + return AXUtilities.is_frame(parent) + + def isClickableElement(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isClickableElement.get(hash(obj)) + if rv is not None: + return rv + + if self.labelIsAncestorOfLabelled(obj): + return False + + if self.hasGridDescendant(obj): + tokens = ["WEB:", obj, "is not clickable: has grid descendant"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return "" + + rv = False + if not self.isFocusModeWidget(obj): + if not AXUtilities.is_focusable(obj): + rv = AXObject.has_action(obj, "click") + else: + rv = AXObject.has_action(obj, "click-ancestor") + + if rv and not AXObject.get_name(obj) and AXObject.supports_text(obj): + string = obj.queryText().getText(0, -1) + if not string.strip(): + rv = not (AXUtilities.is_static(obj) or AXUtilities.is_link(obj)) + + self._isClickableElement[hash(obj)] = rv + return rv + + def isCodeDescendant(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isCodeDescendant(obj) + + rv = self._isCodeDescendant.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.find_ancestor(obj, self.isCode) is not None + self._isCodeDescendant[hash(obj)] = rv + return rv + + def isCode(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isCode(obj) + + return self._getTag(obj) == "code" or "code" in self._getXMLRoles(obj) + + def isDescriptionList(self, obj): + if super().isDescriptionList(obj): + return True + + return self._getTag(obj) == "dl" + + def isDescriptionListTerm(self, obj): + if super().isDescriptionListTerm(obj): + return True + + return self._getTag(obj) == "dt" + + def isDescriptionListDescription(self, obj): + if super().isDescriptionListDescription(obj): + return True + + return self._getTag(obj) == "dd" + + def descriptionListTerms(self, obj): + if not obj: + return [] + + rv = self._descriptionListTerms.get(hash(obj)) + if rv is not None: + return rv + + rv = super().descriptionListTerms(obj) + if not self.inDocumentContent(obj): + return rv + + self._descriptionListTerms[hash(obj)] = rv + return rv + + def valuesForTerm(self, obj): + if not obj: + return [] + + rv = self._valuesForTerm.get(hash(obj)) + if rv is not None: + return rv + + rv = super().valuesForTerm(obj) + if not self.inDocumentContent(obj): + return rv + + self._valuesForTerm[hash(obj)] = rv + return rv + + def getComboBoxValue(self, obj): + attrs = self.objectAttributes(obj, False) + return attrs.get("valuetext", super().getComboBoxValue(obj)) + + def isEditableComboBox(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isEditableComboBox(obj) + + rv = self._isEditableComboBox.get(hash(obj)) + if rv is not None: + return rv + + rv = False + if AXUtilities.is_combo_box(obj): + rv = AXUtilities.is_editable(obj) + + self._isEditableComboBox[hash(obj)] = rv + return rv + + def getEditableComboBoxForItem(self, item): + if not AXUtilities.is_list_item(item): + return None + + listbox = AXObject.find_ancestor(item, AXUtilities.is_list_box) + if listbox is None: + return None + + targets = AXObject.get_relation_targets(listbox, + Atspi.RelationType.CONTROLLED_BY, + self.isEditableComboBox) + if len(targets) == 1: + return targets[0] + + return AXObject.find_ancestor(listbox, self.isEditableComboBox) + + def isItemForEditableComboBox(self, item, comboBox): + if not AXUtilities.is_list_item(item): + return False + if not self.isEditableComboBox(comboBox): + return False + + rv = self.getEditableComboBoxForItem(item) == comboBox + tokens = ["WEB:", item, "is item of", comboBox, ":", rv] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def isDPub(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + roles = self._getXMLRoles(obj) + rv = bool(list(filter(lambda x: x.startswith("doc-"), roles))) + return rv + + def isDPubAbstract(self, obj): + return 'doc-abstract' in self._getXMLRoles(obj) + + def isDPubAcknowledgments(self, obj): + return 'doc-acknowledgments' in self._getXMLRoles(obj) + + def isDPubAfterword(self, obj): + return 'doc-afterword' in self._getXMLRoles(obj) + + def isDPubAppendix(self, obj): + return 'doc-appendix' in self._getXMLRoles(obj) + + def isDPubBacklink(self, obj): + return 'doc-backlink' in self._getXMLRoles(obj) + + def isDPubBiblioref(self, obj): + return 'doc-biblioref' in self._getXMLRoles(obj) + + def isDPubBibliography(self, obj): + return 'doc-bibliography' in self._getXMLRoles(obj) + + def isDPubChapter(self, obj): + return 'doc-chapter' in self._getXMLRoles(obj) + + def isDPubColophon(self, obj): + return 'doc-colophon' in self._getXMLRoles(obj) + + def isDPubConclusion(self, obj): + return 'doc-conclusion' in self._getXMLRoles(obj) + + def isDPubCover(self, obj): + return 'doc-cover' in self._getXMLRoles(obj) + + def isDPubCredit(self, obj): + return 'doc-credit' in self._getXMLRoles(obj) + + def isDPubCredits(self, obj): + return 'doc-credits' in self._getXMLRoles(obj) + + def isDPubDedication(self, obj): + return 'doc-dedication' in self._getXMLRoles(obj) + + def isDPubEndnote(self, obj): + return 'doc-endnote' in self._getXMLRoles(obj) + + def isDPubEndnotes(self, obj): + return 'doc-endnotes' in self._getXMLRoles(obj) + + def isDPubEpigraph(self, obj): + return 'doc-epigraph' in self._getXMLRoles(obj) + + def isDPubEpilogue(self, obj): + return 'doc-epilogue' in self._getXMLRoles(obj) + + def isDPubErrata(self, obj): + return 'doc-errata' in self._getXMLRoles(obj) + + def isDPubExample(self, obj): + return 'doc-example' in self._getXMLRoles(obj) + + def isDPubFootnote(self, obj): + return 'doc-footnote' in self._getXMLRoles(obj) + + def isDPubForeword(self, obj): + return 'doc-foreword' in self._getXMLRoles(obj) + + def isDPubGlossary(self, obj): + return 'doc-glossary' in self._getXMLRoles(obj) + + def isDPubGlossref(self, obj): + return 'doc-glossref' in self._getXMLRoles(obj) + + def isDPubIndex(self, obj): + return 'doc-index' in self._getXMLRoles(obj) + + def isDPubIntroduction(self, obj): + return 'doc-introduction' in self._getXMLRoles(obj) + + def isDPubNoteref(self, obj): + return 'doc-noteref' in self._getXMLRoles(obj) + + def isDPubPagelist(self, obj): + return 'doc-pagelist' in self._getXMLRoles(obj) + + def isDPubPagebreak(self, obj): + return 'doc-pagebreak' in self._getXMLRoles(obj) + + def isDPubPart(self, obj): + return 'doc-part' in self._getXMLRoles(obj) + + def isDPubPreface(self, obj): + return 'doc-preface' in self._getXMLRoles(obj) + + def isDPubPrologue(self, obj): + return 'doc-prologue' in self._getXMLRoles(obj) + + def isDPubPullquote(self, obj): + return 'doc-pullquote' in self._getXMLRoles(obj) + + def isDPubQna(self, obj): + return 'doc-qna' in self._getXMLRoles(obj) + + def isDPubSubtitle(self, obj): + return 'doc-subtitle' in self._getXMLRoles(obj) + + def isDPubToc(self, obj): + return 'doc-toc' in self._getXMLRoles(obj) + + def isErrorMessage(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isErrorMessage(obj) + + rv = self._isErrorMessage.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.has_relation(obj, Atspi.RelationType.ERROR_FOR) + self._isErrorMessage[hash(obj)] = rv + return rv + + def isFakePlaceholderForEntry(self, obj): + if not (obj and self.inDocumentContent(obj) and AXObject.get_parent(obj)): + return False + + if AXUtilities.is_editable(obj): + return False + + entryName = AXObject.get_name(AXObject.find_ancestor(obj, AXUtilities.is_entry)) + if not entryName: + return False + + def _isMatch(x): + try: + string = x.queryText().getText(0, -1).strip() + except Exception: + return False + if entryName != string: + return False + return AXUtilities.is_section(x) or AXUtilities.is_static(x) + + if _isMatch(obj): + return True + + return AXObject.find_descendant(obj, _isMatch) is not None + + def isGrid(self, obj): + return 'grid' in self._getXMLRoles(obj) + + def isGridCell(self, obj): + return 'gridcell' in self._getXMLRoles(obj) + + def isInlineListItem(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isInlineListItem.get(hash(obj)) + if rv is not None: + return rv + + if not AXUtilities.is_list_item(obj): + rv = False + else: + displayStyle = self._getDisplayStyle(obj) + rv = displayStyle and "inline" in displayStyle + + self._isInlineListItem[hash(obj)] = rv + return rv + + def isBlockListDescendant(self, obj): + if not self.isListDescendant(obj): + return False + + return not self.isInlineListDescendant(obj) + + def isListDescendant(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isListDescendant.get(hash(obj)) + if rv is not None: + return rv + + ancestor = AXObject.find_ancestor(obj, AXUtilities.is_list) + rv = ancestor is not None + self._isListDescendant[hash(obj)] = rv + return rv + + def isInlineListDescendant(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isInlineListDescendant.get(hash(obj)) + if rv is not None: + return rv + + if self.isInlineListItem(obj): + rv = True + else: + ancestor = AXObject.find_ancestor(obj, self.isInlineListItem) + rv = ancestor is not None + + self._isInlineListDescendant[hash(obj)] = rv + return rv + + def listForInlineListDescendant(self, obj): + if not self.isInlineListDescendant(obj): + return None + + return AXObject.find_ancestor(obj, AXUtilities.is_list) + + def isFeed(self, obj): + return 'feed' in self._getXMLRoles(obj) + + def isFeedArticle(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + if not AXUtilities.is_article(obj): + return False + + return AXObject.find_ancestor(obj, self.isFeed) is not None + + def isFigure(self, obj): + return 'figure' in self._getXMLRoles(obj) or self._getTag(obj) == 'figure' + + def isLandmark(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isLandmark.get(hash(obj)) + if rv is not None: + return rv + + if AXUtilities.is_landmark(obj): + rv = True + elif self.isLandmarkRegion(obj): + rv = bool(AXObject.get_name(obj)) + else: + roles = self._getXMLRoles(obj) + rv = bool(list(filter(lambda x: x in self.getLandmarkTypes(), roles))) + + self._isLandmark[hash(obj)] = rv + return rv + + def isLandmarkWithoutType(self, obj): + roles = self._getXMLRoles(obj) + return not roles + + def isLandmarkBanner(self, obj): + return 'banner' in self._getXMLRoles(obj) + + def isLandmarkComplementary(self, obj): + return 'complementary' in self._getXMLRoles(obj) + + def isLandmarkContentInfo(self, obj): + return 'contentinfo' in self._getXMLRoles(obj) + + def isLandmarkForm(self, obj): + return 'form' in self._getXMLRoles(obj) + + def isLandmarkMain(self, obj): + return 'main' in self._getXMLRoles(obj) + + def isLandmarkNavigation(self, obj): + return 'navigation' in self._getXMLRoles(obj) + + def isLandmarkRegion(self, obj): + return 'region' in self._getXMLRoles(obj) + + def isLandmarkSearch(self, obj): + return 'search' in self._getXMLRoles(obj) + + def isLiveRegion(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + attrs = self.objectAttributes(obj) + return 'container-live' in attrs + + def isLink(self, obj): + if not obj: + return False + + rv = self._isLink.get(hash(obj)) + if rv is not None: + return rv + + if AXUtilities.is_link(obj) and not self.isAnchor(obj): + rv = True + elif AXUtilities.is_static(obj) \ + and AXUtilities.is_link(AXObject.get_parent(obj)) \ + and AXObject.has_same_non_empty_name(obj, AXObject.get_parent(obj)): + rv = True + else: + rv = False + + self._isLink[hash(obj)] = rv + return rv + + def isNonNavigablePopup(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isNonNavigablePopup.get(hash(obj)) + if rv is not None: + return rv + + rv = AXUtilities.is_tool_tip(obj) \ + and not AXUtilities.is_focusable(obj) + + self._isNonNavigablePopup[hash(obj)] = rv + return rv + + def hasUselessCanvasDescendant(self, obj): + return len(AXUtilities.find_all_canvases(obj, self.isUselessImage)) > 0 + + def isTextSubscriptOrSuperscript(self, obj): + if self.isMath(obj): + return False + + return AXUtilities.is_subscript_or_superscript(obj) + + def isSwitch(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isSwitch(obj) + + return 'switch' in self._getXMLRoles(obj) + + def isNonNavigableEmbeddedDocument(self, obj): + rv = self._isNonNavigableEmbeddedDocument.get(hash(obj)) + if rv is not None: + return rv + + rv = False + if self.isDocument(obj) and self.getDocumentForObject(obj): + try: + name = AXObject.get_name(obj) + except Exception: + rv = True + else: + rv = "doubleclick" in name + + self._isNonNavigableEmbeddedDocument[hash(obj)] = rv + return rv + + def isRedundantSVG(self, obj): + if not self.isSVG(obj) or AXObject.get_child_count(AXObject.get_parent(obj)) == 1: + return False + + rv = self._isRedundantSVG.get(hash(obj)) + if rv is not None: + return rv + + rv = False + parent = AXObject.get_parent(obj) + children = [x for x in AXObject.iter_children(parent, self.isSVG)] + if len(children) == AXObject.get_child_count(parent): + sortedChildren = sorted(children, key=functools.cmp_to_key(self.sizeComparison)) + if obj != sortedChildren[-1]: + objExtents = self.getExtents(obj, 0, -1) + largestExtents = self.getExtents(sortedChildren[-1], 0, -1) + rv = self.intersection(objExtents, largestExtents) == tuple(objExtents) + + self._isRedundantSVG[hash(obj)] = rv + return rv + + def isCustomImage(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isCustomImage.get(hash(obj)) + if rv is not None: + return rv + + rv = False + if self.isCustomElement(obj) and self.hasExplicitName(obj) \ + and AXUtilities.is_section(obj) \ + and AXObject.supports_text(obj) \ + and not re.search(r'[^\s\ufffc]', obj.queryText().getText(0, -1)): + for child in AXObject.iter_children(obj): + if not (AXUtilities.is_image_or_canvas(child) or self.isSVG(child)): + break + else: + rv = True + + self._isCustomImage[hash(obj)] = rv + return rv + + def isUselessImage(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isUselessImage.get(hash(obj)) + if rv is not None: + return rv + + rv = True + if not (AXUtilities.is_image_or_canvas(obj) or self.isSVG(obj)): + rv = False + if rv and (AXObject.get_name(obj) \ + or AXObject.get_description(obj) \ + or self.hasLongDesc(obj)): + rv = False + if rv and (self.isClickableElement(obj) and not self.hasExplicitName(obj)): + rv = False + if rv and AXUtilities.is_focusable(obj): + rv = False + if rv and AXUtilities.is_link(AXObject.get_parent(obj)) and not self.hasExplicitName(obj): + uri = self.uri(AXObject.get_parent(obj)) + if uri and not uri.startswith('javascript'): + rv = False + if rv and AXObject.supports_image(obj): + image = obj.queryImage() + if image.imageDescription: + rv = False + elif not self.hasExplicitName(obj) and not self.isRedundantSVG(obj): + width, height = image.getImageSize() + if width > 25 and height > 25: + rv = False + if rv and AXObject.supports_text(obj): + rv = self.queryNonEmptyText(obj) is None + if rv and AXObject.get_child_count(obj): + for i in range(min(AXObject.get_child_count(obj), 50)): + if not self.isUselessImage(AXObject.get_child(obj, i)): + rv = False + break + + self._isUselessImage[hash(obj)] = rv + return rv + + def hasValidName(self, obj): + name = AXObject.get_name(obj) + if not name: + return False + + if len(name.split()) > 1: + return True + + parsed = urllib.parse.parse_qs(name) + if len(parsed) > 2: + tokens = ["WEB: name of", obj, "is suspected query string"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if len(name) == 1 and ord(name) in range(0xe000, 0xf8ff): + tokens = ["WEB: name of", obj, "is in unicode private use area"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + return True + + def isUselessEmptyElement(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isUselessEmptyElement.get(hash(obj)) + if rv is not None: + return rv + + roles = [Atspi.Role.PARAGRAPH, + Atspi.Role.SECTION, + Atspi.Role.STATIC, + Atspi.Role.TABLE_ROW] + role = AXObject.get_role(obj) + if role not in roles and not self.isAriaAlert(obj): + rv = False + elif AXUtilities.is_focusable(obj): + rv = False + elif AXUtilities.is_editable(obj): + rv = False + elif self.hasValidName(obj) \ + or AXObject.get_description(obj) or AXObject.get_child_count(obj): + rv = False + elif AXObject.supports_text(obj) and obj.queryText().characterCount \ + and obj.queryText().getText(0, -1) != AXObject.get_name(obj): + rv = False + elif AXObject.supports_action(obj): + names = AXObject.get_action_names(obj) + ignore = ["click-ancestor", "show-context-menu", "do-default"] + names = list(filter(lambda x: x not in ignore, names)) + rv = not names + else: + rv = True + + self._isUselessEmptyElement[hash(obj)] = rv + return rv + + def isParentOfNullChild(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isParentOfNullChild.get(hash(obj)) + if rv is not None: + return rv + + rv = False + childCount = AXObject.get_child_count(obj) + if childCount and AXObject.get_child(obj, 0) is None: + tokens = ["ERROR: ", obj, "reports", childCount, + "children, but AXObject.get_child(obj, 0) is None"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + + self._isParentOfNullChild[hash(obj)] = rv + return rv + + def hasExplicitName(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + attrs = self.objectAttributes(obj) + return attrs.get('explicit-name') == 'true' + + def hasLongDesc(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._hasLongDesc.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.has_action(obj, "showlongdesc") + self._hasLongDesc[hash(obj)] = rv + return rv + + def hasVisibleCaption(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().hasVisibleCaption(obj) + + if not (self.isFigure(obj) or AXObject.supports_table(obj)): + return False + + rv = self._hasVisibleCaption.get(hash(obj)) + if rv is not None: + return rv + + labels = self.labelsForObject(obj) + + def isVisibleCaption(x): + return AXUtilities.is_caption(x) and self.isShowingAndVisible(x) + + rv = bool(list(filter(isVisibleCaption, labels))) + self._hasVisibleCaption[hash(obj)] = rv + return rv + + def hasDetails(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().hasDetails(obj) + + rv = self._hasDetails.get(hash(obj)) + if rv is not None: + return rv + + relation = AXObject.get_relation(obj, Atspi.RelationType.DETAILS) + rv = relation and relation.get_n_targets() > 0 + self._hasDetails[hash(obj)] = rv + return rv + + def detailsIn(self, obj): + if not self.hasDetails(obj): + return [] + + return AXObject.get_relation_targets(obj, Atspi.RelationType.DETAILS) + + def isDetails(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().isDetails(obj) + + rv = self._isDetails.get(hash(obj)) + if rv is not None: + return rv + + relation = AXObject.get_relation(obj, Atspi.RelationType.DETAILS_FOR) + rv = relation and relation.get_n_targets() > 0 + self._isDetails[hash(obj)] = rv + return rv + + def detailsFor(self, obj): + if not self.isDetails(obj): + return [] + + return AXObject.get_relation_targets(obj, Atspi.RelationType.DETAILS_FOR) + + def popupType(self, obj): + if not (obj and self.inDocumentContent(obj)): + return 'false' + + attrs = self.objectAttributes(obj) + return attrs.get('haspopup', 'false').lower() + + def inferLabelFor(self, obj): + if not self.shouldInferLabelFor(obj): + return None, [] + + rv = self._inferredLabels.get(hash(obj)) + if rv is not None: + return rv + + rv = self._script.labelInference.infer(obj, False) + self._inferredLabels[hash(obj)] = rv + return rv + + def shouldInferLabelFor(self, obj): + if not self.inDocumentContent() or self.isWebAppDescendant(obj): + return False + + rv = self._shouldInferLabelFor.get(hash(obj)) + if rv and not self._script._lastCommandWasCaretNav: + return not self._script.inSayAll() + if rv is False: + return rv + + role = AXObject.get_role(obj) + name = AXObject.get_name(obj) + if name: + rv = False + elif self._getXMLRoles(obj): + rv = False + elif not rv: + roles = [Atspi.Role.CHECK_BOX, + Atspi.Role.COMBO_BOX, + Atspi.Role.ENTRY, + Atspi.Role.LIST_BOX, + Atspi.Role.PASSWORD_TEXT, + Atspi.Role.RADIO_BUTTON] + rv = role in roles and not self.displayedLabel(obj) + + self._shouldInferLabelFor[hash(obj)] = rv + + # TODO - JD: This is private. + if self._script._lastCommandWasCaretNav \ + and role not in [Atspi.Role.RADIO_BUTTON, Atspi.Role.CHECK_BOX]: + return False + + return rv + + def displayedLabel(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().displayedLabel(obj) + + rv = self._displayedLabelText.get(hash(obj)) + if rv is not None: + return rv + + labels = self.labelsForObject(obj) + strings = [AXObject.get_name(label) + or self.displayedText(label) for label in labels if label is not None] + rv = " ".join(strings) + + self._displayedLabelText[hash(obj)] = rv + return rv + + def labelsForObject(self, obj): + if not obj: + return [] + + rv = self._labelsForObject.get(hash(obj)) + if rv is not None: + return rv + + rv = super().labelsForObject(obj) + if not self.inDocumentContent(obj): + return rv + + self._labelsForObject[hash(obj)] = rv + return rv + + def isSpinnerEntry(self, obj): + if not self.inDocumentContent(obj): + return False + + if not AXUtilities.is_editable(obj): + return False + + if AXUtilities.is_spin_button(obj) or AXUtilities.is_spin_button(AXObject.get_parent(obj)): + return True + + return False + + def eventIsSpinnerNoise(self, event): + if not self.isSpinnerEntry(event.source): + return False + + if event.type.startswith("object:text-changed") \ + or event.type.startswith("object:text-selection-changed"): + lastKey, mods = self.lastKeyAndModifiers() + if lastKey in ["Down", "Up"]: + return True + + return False + + def treatEventAsSpinnerValueChange(self, event): + if event.type.startswith("object:text-caret-moved") and self.isSpinnerEntry(event.source): + lastKey, mods = self.lastKeyAndModifiers() + if lastKey in ["Down", "Up"]: + obj, offset = self.getCaretContext() + return event.source == obj + + return False + + def eventIsBrowserUINoise(self, event): + if self.inDocumentContent(event.source): + return False + + if event.type.startswith("object:text-") \ + and self.isSingleLineAutocompleteEntry(event.source): + lastKey, mods = self.lastKeyAndModifiers() + return lastKey == "Return" + if event.type.startswith("object:text-") or event.type.endswith("accessible-name"): + return AXUtilities.is_status_bar(event.source) or AXUtilities.is_label(event.source) + if event.type.startswith("object:children-changed"): + return True + + return False + + def eventIsAutocompleteNoise(self, event, documentFrame=None): + inContent = documentFrame or self.inDocumentContent(event.source) + if not inContent: + return False + + def isListBoxItem(x): + return AXUtilities.is_list_box(AXObject.get_parent(x)) + + def isMenuItem(x): + return AXUtilities.is_menu(AXObject.get_parent(x)) + + def isComboBoxItem(x): + return AXUtilities.is_combo_box(AXObject.get_parent(x)) + + if AXUtilities.is_editable(event.source) \ + and event.type.startswith("object:text-"): + obj, offset = self.getCaretContext(documentFrame) + if isListBoxItem(obj) or isMenuItem(obj): + return True + + if obj == event.source and isComboBoxItem(obj): + lastKey, mods = self.lastKeyAndModifiers() + if lastKey in ["Down", "Up"]: + return True + + return False + + def eventIsBrowserUIAutocompleteNoise(self, event): + if self.inDocumentContent(event.source): + return False + + if self._eventIsBrowserUIAutocompleteTextNoise(event): + return True + + return self._eventIsBrowserUIAutocompleteSelectionNoise(event) + + def _eventIsBrowserUIAutocompleteSelectionNoise(self, event): + selection = ["object:selection-changed", "object:state-changed:selected"] + if event.type not in selection: + return False + + if AXUtilities.is_menu_related(event.source) \ + and AXUtilities.is_entry(cthulhu_state.locusOfFocus) \ + and AXUtilities.is_focused(cthulhu_state.locusOfFocus): + lastKey, mods = self.lastKeyAndModifiers() + if lastKey not in ["Down", "Up"]: + return True + + return False + + def _eventIsBrowserUIAutocompleteTextNoise(self, event): + if not event.type.startswith("object:text-") \ + or not cthulhu_state.locusOfFocus \ + or not self.isSingleLineAutocompleteEntry(event.source): + return False + + if not AXUtilities.is_selectable(cthulhu_state.locusOfFocus): + return False + + if AXUtilities.is_menu_item_of_any_kind(cthulhu_state.locusOfFocus) \ + or AXUtilities.is_list_item(cthulhu_state.locusOfFocus): + lastKey, mods = self.lastKeyAndModifiers() + return lastKey in ["Down", "Up"] + + return False + + def eventIsBrowserUIPageSwitch(self, event): + selection = ["object:selection-changed", "object:state-changed:selected"] + if event.type not in selection: + return False + + if not AXUtilities.is_page_tab_list_related(event.source): + return False + + if self.inDocumentContent(event.source): + return False + + if not self.inDocumentContent(cthulhu_state.locusOfFocus): + return False + + return True + + def eventIsFromLocusOfFocusDocument(self, event): + if cthulhu_state.locusOfFocus == cthulhu_state.activeWindow: + focus = self.activeDocument() + source = self.getTopLevelDocumentForObject(event.source) + else: + focus = self.getDocumentForObject(cthulhu_state.locusOfFocus) + source = self.getDocumentForObject(event.source) + + tokens = ["WEB: Event doc:", source, ". Focus doc:", focus, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not (source and focus): + return False + + if source == focus: + return True + + if self.isZombie(focus) and not self.isZombie(source): + if self.activeDocument() == source: + msg = "WEB: Treating active doc as locusOfFocus doc" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + return False + + def eventIsIrrelevantSelectionChangedEvent(self, event): + if event.type != "object:selection-changed": + return False + if not cthulhu_state.locusOfFocus: + msg = "WEB: Selection changed event is relevant (no locusOfFocus)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + if event.source == cthulhu_state.locusOfFocus: + msg = "WEB: Selection changed event is relevant (is locusOfFocus)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + if AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.source): + msg = "WEB: Selection changed event is relevant (ancestor of locusOfFocus)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + # There may be other roles where we need to do this. For now, solve the known one. + if AXUtilities.is_page_tab_list(event.source): + tokens = ["WEB: Selection changed event is irrelevant (unrelated", + AXObject.get_role_name(event.source), ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + msg = "WEB: Selection changed event is relevant (no reason found to ignore it)" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + def textEventIsDueToDeletion(self, event): + if not self.inDocumentContent(event.source) \ + or not AXUtilities.is_editable(event.source): + return False + + if self.isDeleteCommandTextDeletionEvent(event) \ + or self.isBackSpaceCommandTextDeletionEvent(event): + return True + + return False + + def textEventIsDueToInsertion(self, event): + if not event.type.startswith("object:text-"): + return False + + if not self.inDocumentContent(event.source) \ + or event.source != cthulhu_state.locusOfFocus \ + or not AXUtilities.is_editable(event.source): + return False + + if isinstance(cthulhu_state.lastInputEvent, input_event.KeyboardEvent): + inputEvent = cthulhu_state.lastNonModifierKeyEvent + return inputEvent and inputEvent.isPrintableKey() and not inputEvent.modifiers + + return False + + def textEventIsForNonNavigableTextObject(self, event): + if not event.type.startswith("object:text-"): + return False + + return self._treatObjectAsWhole(event.source) + + def eventIsEOCAdded(self, event): + if not self.inDocumentContent(event.source): + return False + + if event.type.startswith("object:text-changed:insert") \ + and self.EMBEDDED_OBJECT_CHARACTER in event.any_data: + return not re.match(r"[^\s\ufffc]", event.any_data) + + return False + + def caretMovedOutsideActiveGrid(self, event, oldFocus=None): + if not (event and event.type.startswith("object:text-caret-moved")): + return False + + oldFocus = oldFocus or cthulhu_state.locusOfFocus + if not self.isGridDescendant(oldFocus): + return False + + return not self.isGridDescendant(event.source) + + def caretMovedToSamePageFragment(self, event, oldFocus=None): + if not (event and event.type.startswith("object:text-caret-moved")): + return False + + if AXUtilities.is_editable(event.source): + return False + + docURI = self.documentFrameURI() + fragment = urllib.parse.urlparse(docURI).fragment + if not fragment: + return False + + sourceID = self._getID(event.source) + if sourceID and fragment == sourceID: + return True + + oldFocus = oldFocus or cthulhu_state.locusOfFocus + if self.isLink(oldFocus): + link = oldFocus + else: + link = AXObject.find_ancestor(oldFocus, self.isLink) + + return link and self.uri(link) == docURI + + def isChildOfCurrentFragment(self, obj): + parseResult = urllib.parse.urlparse(self.documentFrameURI()) + if not parseResult.fragment: + return False + + def isSameFragment(x): + return self._getID(x) == parseResult.fragment + + return AXObject.find_ancestor(obj, isSameFragment) is not None + + def documentFragment(self, documentFrame): + parseResult = urllib.parse.urlparse(self.documentFrameURI(documentFrame)) + return parseResult.fragment + + def isContentEditableWithEmbeddedObjects(self, obj): + if not (obj and self.inDocumentContent(obj)): + return False + + rv = self._isContentEditableWithEmbeddedObjects.get(hash(obj)) + if rv is not None: + return rv + + rv = False + def hasTextBlockRole(x): + return AXObject.get_role(x) in self._textBlockElementRoles() \ + and not self.isFakePlaceholderForEntry(x) and not self.isStaticTextLeaf(x) + + if self._getTag(obj) in ["input", "textarea"]: + rv = False + elif AXUtilities.is_multi_line_entry(obj): + rv = AXObject.find_descendant(obj, hasTextBlockRole) + elif AXUtilities.is_editable(obj): + rv = hasTextBlockRole(obj) or self.isLink(obj) + elif not self.isDocument(obj): + document = self.getDocumentForObject(obj) + rv = self.isContentEditableWithEmbeddedObjects(document) + + self._isContentEditableWithEmbeddedObjects[hash(obj)] = rv + return rv + + def characterOffsetInParent(self, obj): + start, end, length = self._rangeInParentWithLength(obj) + return start + + def _rangeInParentWithLength(self, obj): + if not obj: + return -1, -1, 0 + + text = self.queryNonEmptyText(AXObject.get_parent(obj)) + if not text: + return -1, -1, 0 + + start, end = self.getHyperlinkRange(obj) + return start, end, text.characterCount + + def getError(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().getError(obj) + + if not AXUtilities.is_invalid_entry(obj): + return False + + try: + self._currentTextAttrs.pop(hash(obj)) + except Exception: + pass + + attrs, start, end = self.textAttributes(obj, 0, True) + error = attrs.get("invalid") + if error == "false": + return False + if error not in ["spelling", "grammar"]: + return True + + return error + + def _getErrorMessageContainer(self, obj): + if not (obj and self.inDocumentContent(obj)): + return None + + if not self.getError(obj): + return None + + relation = AXObject.get_relation(obj, Atspi.RelationType.ERROR_MESSAGE) + if relation: + return relation.get_target(0) + + return None + + def getErrorMessage(self, obj): + return self.expandEOCs(self._getErrorMessageContainer(obj)) + + def isErrorForContents(self, obj, contents=[]): + if not self.isErrorMessage(obj): + return False + + for acc, start, end, string in contents: + if self._getErrorMessageContainer(acc) == obj: + return True + + return False + + def hasNoSize(self, obj): + if not (obj and self.inDocumentContent(obj)): + return super().hasNoSize(obj) + + rv = self._hasNoSize.get(hash(obj)) + if rv is not None: + return rv + + rv = super().hasNoSize(obj) + self._hasNoSize[hash(obj)] = rv + return rv + + def _canHaveCaretContext(self, obj): + rv = self._canHaveCaretContextDecision.get(hash(obj)) + if rv is not None: + return rv + + if obj is None: + return False + if AXObject.is_dead(obj): + msg = "WEB: Dead object cannot have caret context" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + if self.isZombie(obj): + tokens = ["WEB: Zombie object cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + startTime = time.time() + rv = None + if AXUtilities.is_focusable(obj): + tokens = ["WEB: Focusable object can have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + elif AXUtilities.is_editable(obj): + tokens = ["WEB: Editable object can have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + elif AXUtilities.is_landmark(obj): + tokens = ["WEB: Landmark can have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + elif self.isStaticTextLeaf(obj): + tokens = ["WEB: Static text leaf cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isUselessEmptyElement(obj): + tokens = ["WEB: Useless empty element cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isOffScreenLabel(obj): + tokens = ["WEB: Off-screen label cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isNonNavigablePopup(obj): + tokens = ["WEB: Non-navigable popup cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isUselessImage(obj): + tokens = ["WEB: Useless image cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isEmptyAnchor(obj): + tokens = ["WEB: Empty anchor cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isEmptyToolTip(obj): + tokens = ["WEB: Empty tool tip cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isParentOfNullChild(obj): + tokens = ["WEB: Parent of null child cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isPseudoElement(obj): + tokens = ["WEB: Pseudo element cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isFakePlaceholderForEntry(obj): + tokens = ["WEB: Fake placeholder for entry cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isNonInteractiveDescendantOfControl(obj): + tokens = ["WEB: Non interactive descendant of control cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.isHidden(obj): + # We try to do this check only if needed because getting object attributes is + # not as performant, and we cannot use the cached attribute because aria-hidden + # can change frequently depending on the app. + tokens = ["WEB: Hidden object cannot have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = False + elif self.hasNoSize(obj): + tokens = ["WEB: Allowing sizeless object to have caret context", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + else: + tokens = ["WEB: ", obj, f"can have caret context. ({time.time() - startTime:.4f}s)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + + self._canHaveCaretContextDecision[hash(obj)] = rv + msg = f"INFO: _canHaveCaretContext took {time.time() - startTime:.4f}s" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return rv + + def isPseudoElement(self, obj): + return False + + def searchForCaretContext(self, obj): + tokens = ["WEB: Searching for caret context in", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + container = obj + contextObj, contextOffset = None, -1 + while obj: + try: + offset = obj.queryText().caretOffset + except Exception: + tokens = ["WEB: Exception getting caret offset of", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj = None + else: + contextObj, contextOffset = obj, offset + child = self.findChildAtOffset(obj, offset) + if child: + obj = child + else: + break + + if contextObj and not self.isHidden(contextObj): + return self.findNextCaretInOrder(contextObj, max(-1, contextOffset - 1)) + + if self.isDocument(container): + return container, 0 + + return None, -1 + + def _getCaretContextViaLocusOfFocus(self): + obj = cthulhu_state.locusOfFocus + tokens = ["WEB: Getting caret context via locusOfFocus", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not self.inDocumentContent(obj): + return None, -1 + + try: + offset = obj.queryText().caretOffset + except NotImplementedError: + offset = 0 + except Exception: + offset = -1 + + return obj, offset + + def getCaretContext(self, documentFrame=None, getZombieReplicant=False, searchIfNeeded=True): + tokens = ["WEB: Getting caret context for", documentFrame] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not documentFrame or self.isZombie(documentFrame): + documentFrame = self.documentFrame() + tokens = ["WEB: Now getting caret context for", documentFrame] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not documentFrame: + if not searchIfNeeded: + msg = "WEB: Returning None, -1: No document and no search requested." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None, -1 + + obj, offset = self._getCaretContextViaLocusOfFocus() + tokens = ["WEB: Returning", obj, ", ", offset, "(from locusOfFocus)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, offset + + context = self._caretContexts.get(hash(AXObject.get_parent(documentFrame))) + if context is not None: + tokens = ["WEB: Cached context of", documentFrame, "is", context[0], ", ", context[1]] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + tokens = ["WEB: No cached context for", documentFrame, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj, offset = None, -1 + + if not context or not self.isTopLevelDocument(documentFrame): + if not searchIfNeeded: + msg = "WEB: Returning None, -1: No top-level document with context " \ + "and no search requested." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return None, -1 + obj, offset = self.searchForCaretContext(documentFrame) + elif not getZombieReplicant: + obj, offset = context + elif self.isZombie(context[0]): + msg = "WEB: Context is Zombie. Searching for replicant." + debug.printMessage(debug.LEVEL_INFO, msg, True) + obj, offset = self.findContextReplicant() + if obj: + caretObj, caretOffset = self.searchForCaretContext(AXObject.get_parent(obj)) + if caretObj and not self.isZombie(caretObj): + obj, offset = caretObj, caretOffset + else: + obj, offset = context + + tokens = ["WEB: Result context of", documentFrame, "is", obj, ", ", offset, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.setCaretContext(obj, offset, documentFrame) + return obj, offset + + def getCaretContextPathRoleAndName(self, documentFrame=None): + documentFrame = documentFrame or self.documentFrame() + if not documentFrame: + return [-1], None, None + + rv = self._contextPathsRolesAndNames.get(hash(AXObject.get_parent(documentFrame))) + if not rv: + return [-1], None, None + + return rv + + def clearCaretContext(self, documentFrame=None): + self.clearContentCache() + documentFrame = documentFrame or self.documentFrame() + if not documentFrame: + return + + parent = AXObject.get_parent(documentFrame) + self._caretContexts.pop(hash(parent), None) + self._priorContexts.pop(hash(parent), None) + + def handleEventFromContextReplicant(self, event, replicant): + if AXObject.is_dead(replicant): + msg = "WEB: Context replicant is dead." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if not AXObject.is_dead(cthulhu_state.locusOfFocus): + tokens = ["WEB: Not event from context replicant. locusOfFocus", + cthulhu_state.locusOfFocus, "is not dead."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + path, role, name = self.getCaretContextPathRoleAndName() + replicantPath = AXObject.get_path(replicant) + if path != replicantPath: + tokens = ["WEB: Not event from context replicant. Path", path, + " != replicant path", replicantPath] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + replicantRole = AXObject.get_role(replicant) + if role != replicantRole: + tokens = ["WEB: Not event from context replicant. Role", role, + " != replicant role", replicantRole] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + notify = AXObject.get_name(replicant) != name + documentFrame = self.documentFrame() + obj, offset = self._caretContexts.get(hash(AXObject.get_parent(documentFrame))) + + tokens = ["WEB: Is event from context replicant. Notify:", notify] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + cthulhu.setLocusOfFocus(event, replicant, notify) + self.setCaretContext(replicant, offset, documentFrame) + return True + + def _handleEventForRemovedListBoxChild(self, event): + if AXUtilities.is_list_box(event.source): + listBox = event.source + else: + listBox = AXObject.find_ancestor(event.source, AXUtilities.is_list_box) + if listBox is None: + msg = "WEB: Could not find listbox to recover from removed child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + tokens = ["WEB: Checking", listBox, "for focused child."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + AXObject.clear_cache(listBox) + item = AXUtilities.get_focused_object(listBox) + if not AXUtilities.is_list_item(item): + msg = "WEB: Could not find focused list item to recover from removed child." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + names = self._script.pointOfReference.get('names', {}) + oldName = names.get(hash(cthulhu_state.locusOfFocus)) + notify = AXObject.get_name(item) != oldName + + tokens = ["WEB: Recovered from removed child. New focus is: ", item, "0"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cthulhu.setLocusOfFocus(event, item, notify) + self.setCaretContext(item, 0) + return True + + def handleEventForRemovedChild(self, event): + if event.any_data == cthulhu_state.locusOfFocus: + msg = "WEB: Removed child is locusOfFocus." + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif AXObject.find_ancestor(cthulhu_state.locusOfFocus, lambda x: x == event.any_data): + msg = "WEB: Removed child is ancestor of locusOfFocus." + debug.printMessage(debug.LEVEL_INFO, msg, True) + elif self.isSameObject(event.any_data, cthulhu_state.locusOfFocus, True, True): + msg = "WEB: Removed child appears to be replicant of locusOfFocus." + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + return False + + if event.detail1 == -1: + msg = "WEB: Event detail1 is useless." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._handleEventForRemovedListBoxChild(event): + return True + + obj, offset = None, -1 + notify = True + keyString, mods = self.lastKeyAndModifiers() + childCount = AXObject.get_child_count(event.source) + if keyString == "Up": + if event.detail1 >= childCount: + msg = "WEB: Last child removed. Getting new location from end of parent." + debug.printMessage(debug.LEVEL_INFO, msg, True) + obj, offset = self.previousContext(event.source, -1) + elif 0 <= event.detail1 - 1 < childCount: + child = AXObject.get_child(event.source, event.detail1 - 1) + tokens = ["WEB: Getting new location from end of previous child", child, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj, offset = self.previousContext(child, -1) + else: + prevObj = self.findPreviousObject(event.source) + tokens = ["WEB: Getting new location from end of source's previous object", + prevObj, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj, offset = self.previousContext(prevObj, -1) + + elif keyString == "Down": + if event.detail1 == 0: + msg = "WEB: First child removed. Getting new location from start of parent." + debug.printMessage(debug.LEVEL_INFO, msg, True) + obj, offset = self.nextContext(event.source, -1) + elif 0 < event.detail1 < childCount: + child = AXObject.get_child(event.source, event.detail1) + tokens = ["WEB: Getting new location from start of child", event.detail1, + child, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj, offset = self.nextContext(child, -1) + else: + nextObj = self.findNextObject(event.source) + tokens = ["WEB: Getting new location from start of source's next object", + nextObj, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj, offset = self.nextContext(nextObj, -1) + + else: + notify = False + AXObject.clear_cache(event.source) + obj, offset = self.searchForCaretContext(event.source) + if obj is None: + obj = AXUtilities.get_focused_object(event.source) + + # Risk "chattiness" if the locusOfFocus is dead and the object we've found is + # focused and has a different name than the last known focused object. + if obj and AXObject.is_dead(cthulhu_state.locusOfFocus) \ + and AXUtilities.is_focused(obj): + names = self._script.pointOfReference.get('names', {}) + oldName = names.get(hash(cthulhu_state.locusOfFocus)) + notify = AXObject.get_name(obj) != oldName + + if obj: + msg = "WEB: Setting locusOfFocus and context to: %s, %i" % (obj, offset) + cthulhu.setLocusOfFocus(event, obj, notify) + self.setCaretContext(obj, offset) + return True + + tokens = ["WEB: Unable to find context for child removed from", event.source] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + def findContextReplicant(self, documentFrame=None, matchRole=True, matchName=True): + path, oldRole, oldName = self.getCaretContextPathRoleAndName(documentFrame) + obj = self.getObjectFromPath(path) + if obj and matchRole: + if AXObject.get_role(obj) != oldRole: + obj = None + if obj and matchName: + if AXObject.get_name(obj) != oldName: + obj = None + if not obj: + return None, -1 + + obj, offset = self.findFirstCaretContext(obj, 0) + tokens = ["WEB: Context replicant is", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, offset + + def getPriorContext(self, documentFrame=None): + if not documentFrame or self.isZombie(documentFrame): + documentFrame = self.documentFrame() + + if documentFrame: + context = self._priorContexts.get(hash(AXObject.get_parent(documentFrame))) + if context: + return context + + return None, -1 + + def _getPath(self, obj): + rv = self._paths.get(hash(obj)) + if rv is not None: + return rv + + rv = AXObject.get_path(obj) or [-1] + self._paths[hash(obj)] = rv + return rv + + def setCaretContext(self, obj=None, offset=-1, documentFrame=None): + documentFrame = documentFrame or self.documentFrame() + if not documentFrame: + return + + parent = AXObject.get_parent(documentFrame) + oldObj, oldOffset = self._caretContexts.get(hash(parent), (obj, offset)) + self._priorContexts[hash(parent)] = oldObj, oldOffset + self._caretContexts[hash(parent)] = obj, offset + + path = self._getPath(obj) + role = AXObject.get_role(obj) + name = AXObject.get_name(obj) + self._contextPathsRolesAndNames[hash(parent)] = path, role, name + + def findFirstCaretContext(self, obj, offset): + self._canHaveCaretContextDecision = {} + rv = self._findFirstCaretContext(obj, offset) + self._canHaveCaretContextDecision = {} + return rv + + def _findFirstCaretContext(self, obj, offset): + tokens = ["WEB: Looking for first caret context for", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + role = AXObject.get_role(obj) + lookInChild = [Atspi.Role.LIST, + Atspi.Role.INTERNAL_FRAME, + Atspi.Role.TABLE, + Atspi.Role.TABLE_ROW] + if role in lookInChild \ + and AXObject.get_child_count(obj) and not self.treatAsDiv(obj, offset): + firstChild = AXObject.get_child(obj, 0) + tokens = ["WEB: Will look in child", firstChild, "for first caret context"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return self._findFirstCaretContext(firstChild, 0) + + text = self.queryNonEmptyText(obj) + if not text and self._canHaveCaretContext(obj): + tokens = ["WEB: First caret context for non-text context is", obj, "0"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, 0 + + if text and offset >= text.characterCount: + if self.isContentEditableWithEmbeddedObjects(obj) and self.lastInputEventWasCharNav(): + nextObj, nextOffset = self.nextContext(obj, text.characterCount) + if not nextObj: + tokens = ["WEB: No next object found at end of contenteditable", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + elif not self.isContentEditableWithEmbeddedObjects(nextObj): + tokens = ["WEB: Next object", nextObj, + "found at end of contenteditable", obj, "is not editable"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + tokens = ["WEB: First caret context at end of contenteditable", obj, + "is next context", nextObj, ", ", nextOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return nextObj, nextOffset + + tokens = ["WEB: First caret context at end of", obj, ", ", offset, "is", + obj, ", ", text.characterCount] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, text.characterCount + + offset = max(0, offset) + if text: + allText = text.getText(0, -1) + if allText[offset] != self.EMBEDDED_OBJECT_CHARACTER or role == Atspi.Role.ENTRY: + msg = "WEB: First caret context is unchanged" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return obj, offset + + # Descending an element that we're treating as whole can lead to looping/getting stuck. + if self.elementLinesAreSingleChars(obj): + msg = "WEB: EOC in single-char-lines element. Returning context unchanged." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return obj, offset + + child = self.findChildAtOffset(obj, offset) + if not child: + msg = "WEB: Child at offset is null. Returning context unchanged." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return obj, offset + + if self.isDocument(obj): + while self.isUselessEmptyElement(child): + tokens = ["WEB: Child", child, "of", obj, "at offset", offset, "cannot be context."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + offset += 1 + child = self.findChildAtOffset(obj, offset) + + if self.isListItemMarker(child): + tokens = ["WEB: First caret context is next offset in", obj, ":", + offset + 1, "(skipping list item marker child)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, offset + 1 + + if self.isEmptyAnchor(child): + nextObj, nextOffset = self.nextContext(obj, offset) + if nextObj: + tokens = ["WEB: First caret context at end of empty anchor", obj, + "is next context", nextObj, ", ", nextOffset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return nextObj, nextOffset + + if not self._canHaveCaretContext(child): + tokens = ["WEB: Child", child, "cannot be context. Returning", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, offset + + tokens = ["WEB: Looking in child", child, "for first caret context for", obj, ", ", offset] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return self._findFirstCaretContext(child, 0) + + def findNextCaretInOrder(self, obj=None, offset=-1): + startTime = time.time() + rv = self._findNextCaretInOrder(obj, offset) + tokens = ["WEB: Next caret in order for", obj, ", ", offset, ":", + rv[0], ", ", rv[1], f"({time.time() - startTime:.4f}s)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def _findNextCaretInOrder(self, obj=None, offset=-1): + if not obj: + obj, offset = self.getCaretContext() + + if not obj or not self.inDocumentContent(obj): + return None, -1 + + if self._canHaveCaretContext(obj): + text = self.queryNonEmptyText(obj) + if text: + allText = text.getText(0, -1) + for i in range(offset + 1, len(allText)): + child = self.findChildAtOffset(obj, i) + if child and allText[i] != self.EMBEDDED_OBJECT_CHARACTER: + tokens = ["ERROR: Child", child, "found at offset with char '", + allText[i].replace("\n", "\\n"), "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if offset == self.characterOffsetInParent(child): + tokens = ["WEB: Handling error by returning", obj, i] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return obj, i + if self._canHaveCaretContext(child): + if self._treatObjectAsWhole(child, -1): + return child, 0 + return self._findNextCaretInOrder(child, -1) + if allText[i] not in ( + self.EMBEDDED_OBJECT_CHARACTER, self.ZERO_WIDTH_NO_BREAK_SPACE): + return obj, i + elif AXObject.get_child_count(obj) and not self._treatObjectAsWhole(obj, offset): + return self._findNextCaretInOrder(AXObject.get_child(obj, 0), -1) + elif offset < 0 and not self.isTextBlockElement(obj): + return obj, 0 + + # If we're here, start looking up the tree, up to the document. + if self.isTopLevelDocument(obj): + return None, -1 + + while obj and AXObject.get_parent(obj): + if self.isDetachedDocument(AXObject.get_parent(obj)): + obj = self.iframeForDetachedDocument(AXObject.get_parent(obj)) + continue + + parent = AXObject.get_parent(obj) + if self.isZombie(parent): + msg = "WEB: Finding next caret in order. Parent is Zombie." + debug.printMessage(debug.LEVEL_INFO, msg, True) + replicant = self.findReplicant(self.documentFrame(), parent) + if replicant and not self.isZombie(replicant): + parent = replicant + elif AXObject.get_parent(parent): + obj = parent + continue + else: + break + + start, end, length = self._rangeInParentWithLength(obj) + if start + 1 == end and 0 <= start < end <= length: + return self._findNextCaretInOrder(parent, start) + + child = AXObject.get_next_sibling(obj) + if child: + return self._findNextCaretInOrder(child, -1) + obj = parent + + return None, -1 + + def findPreviousCaretInOrder(self, obj=None, offset=-1): + startTime = time.time() + rv = self._findPreviousCaretInOrder(obj, offset) + tokens = ["WEB: Previous caret in order for", obj, ", ", offset, ":", + rv[0], ", ", rv[1], f"({time.time() - startTime:.4f}s)"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return rv + + def _findPreviousCaretInOrder(self, obj=None, offset=-1): + if not obj: + obj, offset = self.getCaretContext() + + if not obj or not self.inDocumentContent(obj): + return None, -1 + + if self._canHaveCaretContext(obj): + text = self.queryNonEmptyText(obj) + if text: + allText = text.getText(0, -1) + if offset == -1 or offset > len(allText): + offset = len(allText) + for i in range(offset - 1, -1, -1): + child = self.findChildAtOffset(obj, i) + if child and allText[i] != self.EMBEDDED_OBJECT_CHARACTER: + tokens = ["ERROR: Child", child, "found at offset with char '", + allText[i].replace("\n", "\\n"), "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if self._canHaveCaretContext(child): + if self._treatObjectAsWhole(child, -1): + return child, 0 + return self._findPreviousCaretInOrder(child, -1) + if allText[i] not in ( + self.EMBEDDED_OBJECT_CHARACTER, self.ZERO_WIDTH_NO_BREAK_SPACE): + return obj, i + elif AXObject.get_child_count(obj) and not self._treatObjectAsWhole(obj, offset): + return self._findPreviousCaretInOrder( + AXObject.get_child(obj, AXObject.get_child_count(obj) - 1), -1) + elif offset < 0 and not self.isTextBlockElement(obj): + return obj, 0 + + # If we're here, start looking up the tree, up to the document. + if self.isTopLevelDocument(obj): + return None, -1 + + while obj and AXObject.get_parent(obj): + if self.isDetachedDocument(AXObject.get_parent(obj)): + obj = self.iframeForDetachedDocument(AXObject.get_parent(obj)) + continue + + parent = AXObject.get_parent(obj) + if self.isZombie(parent): + msg = "WEB: Finding previous caret in order. Parent is Zombie." + debug.printMessage(debug.LEVEL_INFO, msg, True) + replicant = self.findReplicant(self.documentFrame(), parent) + if replicant and not self.isZombie(replicant): + parent = replicant + elif AXObject.get_parent(parent): + obj = parent + continue + else: + break + + start, end, length = self._rangeInParentWithLength(obj) + if start + 1 == end and 0 <= start < end <= length: + return self._findPreviousCaretInOrder(parent, start) + + child = AXObject.get_previous_sibling(obj) + if child: + return self._findPreviousCaretInOrder(child, -1) + obj = parent + + return None, -1 + + def lastQueuedLiveRegion(self): + if self._lastQueuedLiveRegionEvent is None: + return None + + if self._lastQueuedLiveRegionEvent.type.startswith("object:text-changed:insert"): + return self._lastQueuedLiveRegionEvent.source + + if self._lastQueuedLiveRegionEvent.type.startswith("object:children-changed:add"): + return self._lastQueuedLiveRegionEvent.any_data + + return None + + def handleAsLiveRegion(self, event): + if not _settingsManager.getSetting('inferLiveRegions'): + return False + + if not self.isLiveRegion(event.source): + return False + + if not _settingsManager.getSetting('presentLiveRegionFromInactiveTab') \ + and self.getTopLevelDocumentForObject(event.source) != self.activeDocument(): + msg = "WEB: Live region source is not in active tab." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if event.type.startswith("object:text-changed:insert"): + alert = AXObject.find_ancestor(event.source, self.isAriaAlert) + if alert and AXUtilities.get_focused_object(alert) == event.source: + msg = "WEB: Focused source will be presented as part of alert" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if self._lastQueuedLiveRegionEvent \ + and self._lastQueuedLiveRegionEvent.type == event.type \ + and self._lastQueuedLiveRegionEvent.any_data == event.any_data: + msg = "WEB: Event is believed to be duplicate message" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + if isinstance(event.any_data, Atspi.Accessible): + if AXUtilities.is_unknown_or_redundant(event.any_data) \ + and self._getTag(event.any_data) in ["", None, "br"]: + tokens = ["WEB: Child has unknown role and no tag", event.any_data] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if self.lastQueuedLiveRegion() == event.any_data \ + and self._lastQueuedLiveRegionEvent.type != event.type: + msg = "WEB: Event is believed to be redundant live region notification" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + self._lastQueuedLiveRegionEvent = event + return True + + def getPageObjectCount(self, obj): + result = {'landmarks': 0, + 'headings': 0, + 'forms': 0, + 'tables': 0, + 'visitedLinks': 0, + 'unvisitedLinks': 0} + + docframe = self.documentFrame(obj) + tokens = ["WEB: Document frame for", obj, "is", docframe] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + roles = [Atspi.Role.HEADING, + Atspi.Role.LINK, + Atspi.Role.TABLE, + Atspi.Role.FORM, + Atspi.Role.LANDMARK] + + rule = AXCollection.create_match_rule(roles=roles) + matches = AXCollection.get_all_matches(docframe, rule) + + for obj in matches: + if AXUtilities.is_heading(obj): + result['headings'] += 1 + elif AXUtilities.is_form(obj): + result['forms'] += 1 + elif AXUtilities.is_table(obj) and not self.isLayoutOnly(obj): + result['tables'] += 1 + elif AXUtilities.is_link(obj): + if self.isLink(obj): + if AXUtilities.is_visited(obj): + result['visitedLinks'] += 1 + else: + result['unvisitedLinks'] += 1 + elif self.isLandmark(obj): + result['landmarks'] += 1 + + return result + + def getPageSummary(self, obj, onlyIfFound=True): + result = [] + counts = self.getPageObjectCount(obj) + result.append(messages.landmarkCount(counts.get('landmarks', 0), onlyIfFound)) + result.append(messages.headingCount(counts.get('headings', 0), onlyIfFound)) + result.append(messages.formCount(counts.get('forms', 0), onlyIfFound)) + result.append(messages.tableCount(counts.get('tables', 0), onlyIfFound)) + result.append(messages.visitedLinkCount(counts.get('visitedLinks', 0), onlyIfFound)) + result.append(messages.unvisitedLinkCount(counts.get('unvisitedLinks', 0), onlyIfFound)) + result = list(filter(lambda x: x, result)) + if not result: + return "" + + return messages.PAGE_SUMMARY_PREFIX % ", ".join(result) + + def preferDescriptionOverName(self, obj): + if not self.inDocumentContent(obj): + return super().preferDescriptionOverName(obj) + + rv = self._preferDescriptionOverName.get(hash(obj)) + if rv is not None: + return rv + + name = AXObject.get_name(obj) + if len(name) == 1 and ord(name) in range(0xe000, 0xf8ff): + tokens = ["WEB: name of", obj, "is in unicode private use area"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = True + elif AXObject.get_description(obj): + rv = AXUtilities.is_push_button(obj) and len(name) == 1 + else: + rv = False + + self._preferDescriptionOverName[hash(obj)] = rv + return rv + + def _getCtrlShiftSelectionsStrings(self): + """Hacky and to-be-obsoleted method.""" + return [messages.LINE_SELECTED_DOWN, + messages.LINE_UNSELECTED_DOWN, + messages.LINE_SELECTED_UP, + messages.LINE_UNSELECTED_UP] + + def lastInputEventWasCopy(self): + if super().lastInputEventWasCopy(): + return True + + if not self.inDocumentContent(): + return False + + if not self.topLevelObjectIsActiveAndCurrent(): + return False + + if AXObject.supports_action(cthulhu_state.locusOfFocus): + tokens = ["WEB: Treating", cthulhu_state.locusOfFocus, "as source of copy"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + return False diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/sound_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/sound_generator.py new file mode 100644 index 0000000..987a854 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/sound_generator.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for obtaining sounds to be presented for objects.""" + +__id__ = "$Id:$" +__version__ = "$Revision:$" +__date__ = "$Date:$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from cthulhu import settings_manager +from cthulhu import sound_generator + +_settingsManager = settings_manager.getManager() + + +class SoundGenerator(sound_generator.SoundGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateClickable(self, obj, **args): + """Returns an array of sounds indicating obj is clickable.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return [] + + if not args.get('mode', None): + args['mode'] = self._mode + + args['stringType'] = 'clickable' + if self._script.utilities.isClickableElement(obj): + filenames = [self._script.formatting.getString(**args)] + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateHasLongDesc(self, obj, **args): + """Returns an array of sounds indicating obj has a longdesc.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return [] + + if not args.get('mode', None): + args['mode'] = self._mode + + args['stringType'] = 'haslongdesc' + if self._script.utilities.hasLongDesc(obj): + filenames = [self._script.formatting.getString(**args)] + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def generateSound(self, obj, **args): + """Returns an array of sounds for the complete presentation of obj.""" + + if not self._script.utilities.inDocumentContent(obj): + return super().generateSound(obj, **args) + + result = [] + if args.get('formatType') == 'detailedWhereAmI': + oldRole = self._overrideRole('default', args) + elif self._script.utilities.isLink(obj): + oldRole = self._overrideRole(Atspi.Role.LINK, args) + elif self._script.utilities.treatAsDiv(obj): + oldRole = self._overrideRole(Atspi.Role.SECTION, args) + else: + oldRole = self._overrideRole(self._getAlternativeRole(obj, **args), args) + + result.extend(super().generateSound(obj, **args)) + result = list(filter(lambda x: x, result)) + self._restoreRole(oldRole, args) + + return result + + def generateContents(self, contents, **args): + """Returns an array of an array of sounds for the contents.""" + + if not len(contents): + return [] + + result = [] + contents = self._script.utilities.filterContentsForPresentation(contents, False) + for i, content in enumerate(contents): + obj, start, end, string = content + icon = self.generateSound( + obj, startOffset=start, endOffset=end, string=string, + index=i, total=len(contents), **args) + result.append(icon) + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/speech_generator.py new file mode 100644 index 0000000..66d418b --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/speech_generator.py @@ -0,0 +1,851 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2011 Cthulhu Team" \ + "Copyright (c) 2011-2015 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi +import urllib + +from cthulhu import debug +from cthulhu import messages +from cthulhu import object_properties +from cthulhu import cthulhu_state +from cthulhu import settings +from cthulhu import settings_manager +from cthulhu import speech_generator +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + + +class SpeechGenerator(speech_generator.SpeechGenerator): + + def __init__(self, script): + super().__init__(script) + + def _generateOldAncestors(self, obj, **args): + if args.get('index', 0) > 0: + return [] + + priorObj = args.get('priorObj') + if self._script.utilities.isInlineIframeDescendant(priorObj): + return [] + + return super()._generateOldAncestors(obj, **args) + + def _generateNewAncestors(self, obj, **args): + if args.get('index', 0) > 0 \ + and not self._script.utilities.isListDescendant(obj): + return [] + + if self._script.utilities.isInlineIframeDescendant(obj): + return [] + + return super()._generateNewAncestors(obj, **args) + + def _generateAncestors(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateAncestors(obj, **args) + + if self._script.inSayAll() and obj == cthulhu_state.locusOfFocus: + return [] + + result = [] + priorObj = args.get('priorObj') + if priorObj and self._script.utilities.inDocumentContent(priorObj): + priorDoc = self._script.utilities.getDocumentForObject(priorObj) + doc = self._script.utilities.getDocumentForObject(obj) + if priorDoc != doc and not self._script.utilities.getDocumentForObject(doc): + result = [super()._generateName(doc)] + + if not self._script.utilities.getTable(obj) \ + and (self._script.utilities.isLink(obj) \ + or self._script.utilities.isLandmark(obj) \ + or self._script.utilities.isMath(obj) \ + or AXUtilities.is_tool_tip(obj) \ + or AXUtilities.is_status_bar(obj)): + return result + + if self._script.utilities.isItemForEditableComboBox(obj, priorObj): + return result + + args['stopAtRoles'] = [Atspi.Role.DOCUMENT_WEB, + Atspi.Role.EMBEDDED, + Atspi.Role.INTERNAL_FRAME, + Atspi.Role.MATH, + Atspi.Role.MENU_BAR] + args['skipRoles'] = [Atspi.Role.PARAGRAPH, + Atspi.Role.HEADING, + Atspi.Role.LABEL, + Atspi.Role.LINK, + Atspi.Role.LIST_ITEM, + Atspi.Role.TEXT] + args['stopAfterRoles'] = [Atspi.Role.TOOL_BAR] + + if self._script.utilities.isEditableDescendantOfComboBox(obj): + args['skipRoles'].append(Atspi.Role.COMBO_BOX) + + result.extend(super()._generateAncestors(obj, **args)) + + return result + + def _generateAllTextSelection(self, obj, **args): + if self._script.utilities.isZombie(obj) \ + or obj != cthulhu_state.locusOfFocus: + return [] + + # TODO - JD: These (and the default script's) need to + # call utility methods rather than generate it. + return super()._generateAllTextSelection(obj, **args) + + def _generateAnyTextSelection(self, obj, **args): + if self._script.utilities.isZombie(obj) \ + or obj != cthulhu_state.locusOfFocus: + return [] + + # TODO - JD: These (and the default script's) need to + # call utility methods rather than generate it. + return super()._generateAnyTextSelection(obj, **args) + + def _generateHasPopup(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return [] + + result = [] + popupType = self._script.utilities.popupType(obj) + if popupType == 'dialog': + result = [messages.HAS_POPUP_DIALOG] + elif popupType == 'grid': + result = [messages.HAS_POPUP_GRID] + elif popupType == 'listbox': + result = [messages.HAS_POPUP_LISTBOX] + elif popupType in ('menu', 'true'): + result = [messages.HAS_POPUP_MENU] + elif popupType == 'tree': + result = [messages.HAS_POPUP_TREE] + + if result: + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + return result + + def _generateClickable(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return [] + + if self._script.utilities.isFeedArticle(obj): + return [] + + if not args.get('mode', None): + args['mode'] = self._mode + + args['stringType'] = 'clickable' + if self._script.utilities.isClickableElement(obj): + result = [self._script.formatting.getString(**args)] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + return [] + + def _generateDescription(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return super()._generateDescription(obj, **args) + + if self._script.utilities.isZombie(obj): + return [] + + if self._script.utilities.preferDescriptionOverName(obj): + return [] + + role = args.get('role', AXObject.get_role(obj)) + if obj != cthulhu_state.locusOfFocus: + if role in [Atspi.Role.ALERT, Atspi.Role.DIALOG]: + return super()._generateDescription(obj, **args) + if not args.get('inMouseReview'): + return [] + + formatType = args.get('formatType') + if formatType == 'basicWhereAmI' and self._script.utilities.isLiveRegion(obj): + return self._script.liveRegionManager.generateLiveRegionDescription(obj, **args) + + if role == Atspi.Role.TEXT and formatType != 'basicWhereAmI': + return [] + + # TODO - JD: This is private. + if role == Atspi.Role.LINK and self._script._lastCommandWasCaretNav: + return [] + + return super()._generateDescription(obj, **args) + + def _generateHasLongDesc(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return [] + + if not args.get('mode', None): + args['mode'] = self._mode + + args['stringType'] = 'haslongdesc' + if self._script.utilities.hasLongDesc(obj): + result = [self._script.formatting.getString(**args)] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + return [] + + def _generateHasDetails(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return super()._generateHasDetails(obj, **args) + + objs = self._script.utilities.detailsIn(obj) + if not objs: + return [] + + def objString(x): + return str.strip(f"{AXObject.get_name(x)} {self.getLocalizedRoleName(x)}") + + toPresent = ", ".join(set(map(objString, objs))) + + args['stringType'] = 'hasdetails' + result = [self._script.formatting.getString(**args) % toPresent] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + def _generateAllDetails(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + objs = self._script.utilities.detailsIn(obj) + if not objs: + container = AXObject.find_ancestor(obj, self._script.utilities.hasDetails) + objs = self._script.utilities.detailsIn(container) + + if not objs: + return [] + + args['stringType'] = 'hasdetails' + result = [self._script.formatting.getString(**args) % ""] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + result = [] + for o in objs: + result.append(self.getLocalizedRoleName(o)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + string = self._script.utilities.expandEOCs(o) + if not string.strip(): + continue + + result.append(string) + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + result.extend(self._generatePause(o)) + + return result + + def _generateDetailsFor(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return super()._generateDetailsFor(obj, **args) + + objs = self._script.utilities.detailsFor(obj) + if not objs: + return [] + + if args.get('leaving'): + return [] + + lastKey, mods = self._script.utilities.lastKeyAndModifiers() + if (lastKey in ['Down', 'Right'] or self._script.inSayAll()) and args.get('startOffset'): + return [] + if lastKey in ['Up', 'Left']: + text = self._script.utilities.queryNonEmptyText(obj) + if text and args.get('endOffset') not in [None, text.characterCount]: + return [] + + result = [] + objArgs = {'stringType': 'detailsfor', 'mode': args.get('mode')} + for o in objs: + string = self._script.utilities.displayedText(o) or self.getLocalizedRoleName(o) + words = string.split() + if len(words) > 5: + words = words[0:5] + ['...'] + + result.append(self._script.formatting.getString(**objArgs) % " ".join(words)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + result.extend(self._generatePause(o, **objArgs)) + + return result + + def _generateLabelOrName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateLabelOrName(obj, **args) + + if self._script.utilities.isTextBlockElement(obj) \ + and not self._script.utilities.isLandmark(obj) \ + and not self._script.utilities.isDocument(obj) \ + and not self._script.utilities.isDPub(obj) \ + and not self._script.utilities.isContentSuggestion(obj): + return [] + + priorObj = args.get("priorObj") + if obj == priorObj: + return [] + + if priorObj and priorObj in self._script.utilities.labelsForObject(obj): + return [] + + objName = AXObject.get_name(obj) + descendant = args.get("ancestorOf") + if descendant and priorObj and objName and objName == AXObject.get_name(priorObj): + tokens = ["WEB: ", descendant, "'s ancestor", obj, "has same name as priorObj", + priorObj, ". Not generating labelOrName."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.MENU and self._script.utilities.isPopupMenuForCurrentItem(obj): + tokens = ["WEB: ", obj, "is popup menu for current item."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + if self._script.utilities.isContentEditableWithEmbeddedObjects(obj) \ + or self._script.utilities.isDocument(obj): + lastKey, mods = self._script.utilities.lastKeyAndModifiers() + if lastKey in ["Home", "End", "Up", "Down", "Left", "Right", "Page_Up", "Page_Down"]: + return [] + + if AXUtilities.is_page_tab(priorObj) and AXObject.get_name(priorObj) == objName: + return [] + + if objName: + name = objName + if not self._script.utilities.hasExplicitName(obj): + name = name.strip() + + if self._script.utilities.shouldVerbalizeAllPunctuation(obj): + name = self._script.utilities.verbalizeAllPunctuation(name) + + result = [name] + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + return result + + if AXUtilities.is_check_box(obj): + gridCell = AXObject.find_ancestor(obj, self._script.utilities.isGridCell) + if gridCell: + return super()._generateLabelOrName(gridCell, **args) + + return super()._generateLabelOrName(obj, **args) + + def _generateName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateName(obj, **args) + + if self._script.utilities.isTextBlockElement(obj) \ + and not self._script.utilities.isLandmark(obj) \ + and not self._script.utilities.isDPub(obj) \ + and not args.get('inFlatReview'): + return [] + + if self._script.utilities.hasVisibleCaption(obj): + return [] + + if self._script.utilities.isFigure(obj) and args.get('ancestorOf'): + caption = args.get('ancestorOf') + if not AXUtilities.is_caption(caption): + caption = AXObject.find_ancestor(caption, AXUtilities.is_caption) + if caption and hash(obj) in self._script.utilities.labelTargets(caption): + return [] + + role = args.get('role', AXObject.get_role(obj)) + + # TODO - JD: Once the formatting strings are vastly cleaned up + # or simply removed, hacks like this won't be needed. + if role in [Atspi.Role.COMBO_BOX, Atspi.Role.SPIN_BUTTON]: + return super()._generateName(obj, **args) + + if AXObject.get_name(obj): + if self._script.utilities.preferDescriptionOverName(obj): + result = [AXObject.get_description(obj)] + elif self._script.utilities.isLink(obj) \ + and not self._script.utilities.hasExplicitName(obj): + return [] + else: + name = AXObject.get_name(obj) + if not self._script.utilities.hasExplicitName(obj): + name = name.strip() + result = [name] + + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + return result + + return super()._generateName(obj, **args) + + def _generateLabel(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateLabel(obj, **args) + + if self._script.utilities.isTextBlockElement(obj): + return [] + + label, objects = self._script.utilities.inferLabelFor(obj) + if label: + result = [label] + result.extend(self.voice(speech_generator.DEFAULT, obj=obj, **args)) + return result + + return super()._generateLabel(obj, **args) + + def _generateNewNodeLevel(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if self._script.utilities.isTextBlockElement(obj) \ + or self._script.utilities.isLink(obj): + return [] + + return super()._generateNewNodeLevel(obj, **args) + + def _generateLeaving(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not args.get('leaving'): + return [] + + if self._script.utilities.inDocumentContent(obj) \ + and not self._script.utilities.inDocumentContent(cthulhu_state.locusOfFocus): + result = [''] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + return super()._generateLeaving(obj, **args) + + def _generateNewRadioButtonGroup(self, obj, **args): + # TODO - JD: The default speech generator's method determines group membership + # via the member-of relation. We cannot count on that here. Plus, radio buttons + # on the web typically live in a group which is labelled. Thus the new-ancestor + # presentation accomplishes the same thing. Unless this can be further sorted out, + # try to filter out some of the noise.... + return [] + + def _generateNumberOfChildren(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or _settingsManager.getSetting('speechVerbosityLevel') == settings.VERBOSITY_LEVEL_BRIEF: + return [] + + # We handle things even for non-document content due to issues in + # other toolkits (e.g. exposing list items to us that are not + # exposed to sighted users) + roles = [Atspi.Role.DESCRIPTION_LIST, + Atspi.Role.LIST, + Atspi.Role.LIST_BOX, + 'ROLE_FEED'] + role = args.get('role', AXObject.get_role(obj)) + if role not in roles: + return super()._generateNumberOfChildren(obj, **args) + + setsize = self._script.utilities.getSetSize(AXObject.get_child(obj, 0)) + if setsize is None: + children = [] + if self._script.utilities.isDescriptionList(obj): + children = self._script.utilities.descriptionListTerms(obj) + elif role in [Atspi.Role.LIST, Atspi.Role.LIST_BOX]: + children = [x for x in AXObject.iter_children(obj, AXUtilities.is_list_item)] + setsize = len(children) + + if not setsize: + return [] + + if self._script.utilities.isDescriptionList(obj): + result = [messages.descriptionListTermCount(setsize)] + elif role == 'ROLE_FEED': + result = [messages.feedArticleCount(setsize)] + else: + result = [messages.listItemCount(setsize)] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + # TODO - JD: Yet another dumb generator method we should kill. + def _generateTextRole(self, obj, **args): + return self._generateRoleName(obj, **args) + + def getLocalizedRoleName(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super().getLocalizedRoleName(obj, **args) + + roledescription = self._script.utilities.getRoleDescription(obj) + if roledescription: + return roledescription + + return super().getLocalizedRoleName(obj, **args) + + def _generateRealActiveDescendantDisplayedText(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateRealActiveDescendantDisplayedText(obj, **args) + + rad = self._script.utilities.realActiveDescendant(obj) + return self._generateDisplayedText(rad, **args) + + def _generateRoleName(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not self._script.utilities.inDocumentContent(obj): + return super()._generateRoleName(obj, **args) + + if obj == args.get('priorObj'): + return [] + + result = [] + roledescription = self._script.utilities.getRoleDescription(obj) + if roledescription: + result = [roledescription] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + role = args.get('role', AXObject.get_role(obj)) + enabled, disabled = self._getEnabledAndDisabledContextRoles() + if role in disabled: + return [] + + force = args.get('force', False) + start = args.get('startOffset') + end = args.get('endOffset') + index = args.get('index', 0) + total = args.get('total', 1) + + if not force: + doNotSpeak = [Atspi.Role.FOOTER, + Atspi.Role.FORM, + Atspi.Role.LABEL, + Atspi.Role.MENU_ITEM, + Atspi.Role.PARAGRAPH, + Atspi.Role.SECTION, + Atspi.Role.REDUNDANT_OBJECT, + Atspi.Role.UNKNOWN] + else: + doNotSpeak = [Atspi.Role.UNKNOWN] + + if not force: + doNotSpeak.append(Atspi.Role.TABLE_CELL) + doNotSpeak.append(Atspi.Role.TEXT) + doNotSpeak.append(Atspi.Role.STATIC) + if args.get('string'): + doNotSpeak.append("ROLE_CONTENT_SUGGESTION") + if args.get('formatType', 'unfocused') != 'basicWhereAmI': + doNotSpeak.append(Atspi.Role.LIST_ITEM) + doNotSpeak.append(Atspi.Role.LIST) + if (start or end): + doNotSpeak.append(Atspi.Role.DOCUMENT_FRAME) + doNotSpeak.append(Atspi.Role.DOCUMENT_WEB) + doNotSpeak.append(Atspi.Role.ALERT) + if self._script.utilities.isAnchor(obj): + doNotSpeak.append(AXObject.get_role(obj)) + if total > 1: + doNotSpeak.append(Atspi.Role.ROW_HEADER) + if self._script.utilities.isMenuInCollapsedSelectElement(obj): + doNotSpeak.append(Atspi.Role.MENU) + + lastKey, mods = self._script.utilities.lastKeyAndModifiers() + isEditable = AXUtilities.is_editable(obj) + + if isEditable and not self._script.utilities.isContentEditableWithEmbeddedObjects(obj): + if ((lastKey in ["Down", "Right"] and not mods) or self._script.inSayAll()) and start: + return [] + if lastKey in ["Up", "Left"] and not mods: + text = self._script.utilities.queryNonEmptyText(obj) + if text and end not in [None, text.characterCount]: + return [] + if role not in doNotSpeak: + result.append(self.getLocalizedRoleName(obj, **args)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + elif isEditable and self._script.utilities.isDocument(obj): + parent = AXObject.get_parent(obj) + if parent and not AXUtilities.is_editable(parent) \ + and lastKey not in \ + ["Home", "End", "Up", "Down", "Left", "Right", "Page_Up", "Page_Down"]: + result.append(object_properties.ROLE_EDITABLE_CONTENT) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + elif role == Atspi.Role.HEADING: + if index == total - 1 or not self._script.utilities.isFocusableWithMathChild(obj): + level = self._script.utilities.headingLevel(obj) + if level: + result.append(object_properties.ROLE_HEADING_LEVEL_SPEECH % { + 'role': self.getLocalizedRoleName(obj, **args), + 'level': level}) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + else: + result.append(self.getLocalizedRoleName(obj, **args)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + elif self._script.utilities.isLink(obj): + if AXUtilities.is_image(AXObject.get_parent(obj)): + result.append(messages.IMAGE_MAP_LINK) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + else: + if self._script.utilities.hasUselessCanvasDescendant(obj): + result.append(self.getLocalizedRoleName(obj, role=Atspi.Role.IMAGE)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + if index == total - 1 or not self._script.utilities.isFocusableWithMathChild(obj): + result.append(self.getLocalizedRoleName(obj, **args)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + elif role not in doNotSpeak and args.get('priorObj') != obj: + result.append(self.getLocalizedRoleName(obj, **args)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + if self._script.utilities.isMath(obj) and not self._script.utilities.isMathTopLevel(obj): + return result + + def speakRoles(x): + return AXUtilities.is_heading(x) or AXUtilities.is_link(x) + + ancestor = AXObject.find_ancestor(obj, speakRoles) + if ancestor and AXObject.get_role(ancestor) != role \ + and (index == total - 1 or AXObject.get_name(obj) == AXObject.get_name(ancestor)): + result.extend(self._generateRoleName(ancestor)) + + return result + + def _generatePageSummary(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return [] + + onlyIfFound = args.get('formatType') != 'detailedWhereAmI' + + string = self._script.utilities.getPageSummary(obj, onlyIfFound) + if not string: + return [] + + result = [string] + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + def _generateSiteDescription(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return [] + + link_uri = self._script.utilities.uri(obj) + if not link_uri: + return [] + + link_uri_info = urllib.parse.urlparse(link_uri) + doc_uri = self._script.utilities.documentFrameURI() + if not doc_uri: + return [] + + result = [] + doc_uri_info = urllib.parse.urlparse(doc_uri) + if link_uri_info[1] == doc_uri_info[1]: + if link_uri_info[2] == doc_uri_info[2]: + result.append(messages.LINK_SAME_PAGE) + else: + result.append(messages.LINK_SAME_SITE) + else: + linkdomain = link_uri_info[1].split('.') + docdomain = doc_uri_info[1].split('.') + if len(linkdomain) > 1 and len(docdomain) > 1 \ + and linkdomain[-1] == docdomain[-1] \ + and linkdomain[-2] == docdomain[-2]: + result.append(messages.LINK_SAME_SITE) + else: + result.append(messages.LINK_DIFFERENT_SITE) + + if result: + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + return result + + def _generateExpandedEOCs(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateExpandedEOCs(obj, **args) + + result = [] + startOffset = args.get('startOffset', 0) + endOffset = args.get('endOffset', -1) + text = self._script.utilities.expandEOCs(obj, startOffset, endOffset) + if text: + result.append(text) + return result + + def _generatePositionInList(self, obj, **args): + if AXUtilities.is_list_item(obj): + thisObjIndex = args.get('index', 0) + objCount = args.get('total', 1) + if thisObjIndex + 1 < objCount: + return [] + + if args.get('formatType') not in ['basicWhereAmI', 'detailedWhereAmI']: + if args.get('priorObj') == obj: + return [] + + return super()._generatePositionInList(obj, **args) + + def _generateUnselectedCell(self, obj, **args): + if not self._script.inFocusMode(): + return [] + + return super()._generateUnselectedCell(obj, **args) + + def _generateRealTableCell(self, obj, **args): + result = super()._generateRealTableCell(obj, **args) + if not self._script.inFocusMode(): + return result + + if _settingsManager.getSetting('speakCellCoordinates'): + label = self._script.utilities.labelForCellCoordinates(obj) + if label: + result.append(label) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + return result + + row, col = self._script.utilities.coordinatesForCell(obj) + if self._script.utilities.cellRowChanged(obj): + result.append(messages.TABLE_ROW % (row + 1)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + if self._script.utilities.cellColumnChanged(obj): + result.append(messages.TABLE_COLUMN % (col + 1)) + result.extend(self.voice(speech_generator.SYSTEM, obj=obj, **args)) + + return result + + def _generateTableCellRow(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + return super()._generateTableCellRow(obj, **args) + + if not self._script.utilities.shouldReadFullRow(obj): + return self._generateRealTableCell(obj, **args) + + row = AXObject.find_ancestor(obj, AXUtilities.is_table_row) + if row and AXObject.get_name(row) and not self._script.utilities.isLayoutOnly(row): + return self.generate(row) + + return super()._generateTableCellRow(obj, **args) + + def _generateRowHeader(self, obj, **args): + if self._script.utilities.lastInputEventWasLineNav(): + return [] + + return super()._generateRowHeader(obj) + + def generateSpeech(self, obj, **args): + if not self._script.utilities.inDocumentContent(obj): + tokens = ["WEB:", obj, "is not in document content. Calling default speech generator."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return super().generateSpeech(obj, **args) + + tokens = ["WEB: Generating speech for document object", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + result = [] + if args.get('formatType') == 'detailedWhereAmI': + oldRole = self._overrideRole('default', args) + elif self._script.utilities.isLink(obj): + oldRole = self._overrideRole(Atspi.Role.LINK, args) + elif self._script.utilities.isCustomImage(obj): + oldRole = self._overrideRole(Atspi.Role.IMAGE, args) + elif self._script.utilities.treatAsDiv(obj, offset=args.get('startOffset')): + oldRole = self._overrideRole(Atspi.Role.SECTION, args) + else: + oldRole = self._overrideRole(self._getAlternativeRole(obj, **args), args) + + if 'priorObj' not in args: + document = self._script.utilities.getTopLevelDocumentForObject(obj) + args['priorObj'] = self._script.utilities.getPriorContext(document)[0] + + start = args.get("startOffset", 0) + end = args.get("endOffset", -1) + args["language"], args["dialect"] = \ + self._script.utilities.getLanguageAndDialectForSubstring(obj, start, end) + + if not result: + result = list(filter(lambda x: x, super().generateSpeech(obj, **args))) + + self._restoreRole(oldRole, args) + tokens = ["WEB: Speech generation for document object", obj, "complete."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return result + + def generateContents(self, contents, **args): + if not len(contents): + return [] + + result = [] + contents = self._script.utilities.filterContentsForPresentation(contents, True) + tokens = ["WEB: Generating speech contents (length:", len(contents), ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + for i, content in enumerate(contents): + obj, start, end, string = content + tokens = ["ITEM", i, ": ", obj, "start: ", start, ", end: ", end, "'", string, "'"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + utterance = self.generateSpeech( + obj, startOffset=start, endOffset=end, string=string, + index=i, total=len(contents), **args) + if isinstance(utterance, list): + def isNotEmptyList(x): + return not (isinstance(x, list) and not x) + + utterance = list(filter(isNotEmptyList, utterance)) + if utterance and utterance[0]: + result.append(utterance) + args['priorObj'] = obj + + if not result: + if self._script.inSayAll(treatInterruptedAsIn=False) \ + or not _settingsManager.getSetting('speakBlankLines') \ + or args.get('formatType') == 'ancestor': + string = "" + else: + string = messages.BLANK + result = [string, self.voice(speech_generator.DEFAULT, **args)] + + return result diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/tutorial_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/tutorial_generator.py new file mode 100644 index 0000000..b9dfb42 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/scripts/web/tutorial_generator.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Cthulhu Team." +__license__ = "LGPL" + +from cthulhu import messages +from cthulhu import tutorialgenerator + + +class TutorialGenerator(tutorialgenerator.TutorialGenerator): + def __init__(self, script): + super().__init__(script) + + def _getFocusModeTutorial(self, obj, alreadyFocused, forceTutorial): + binding = self._getBindingsForHandler("togglePresentationModeHandler") + if not binding: + return [] + + return [messages.MODE_FOCUS_TUTORIAL % binding] + + def _getModeTutorial(self, obj, alreadyFocused, forceTutorial): + if self._script.utilities.isFocusModeWidget(obj) \ + and not self._script.useFocusMode(obj): + return self._getFocusModeTutorial(obj, alreadyFocused, forceTutorial) + + return super()._getModeTutorial(obj, alreadyFocused, forceTutorial) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings.py new file mode 100644 index 0000000..bfac14d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings.py @@ -0,0 +1,447 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Manages the settings for Cthulhu. This will defer to user settings first, but +fallback to local settings if the user settings doesn't exist (e.g., in the +case of gdm) or doesn't have the specified attribute.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +from . import messages +from .acss import ACSS + +userCustomizableSettings = [ + "cthulhuModifierKeys", + "enableSpeech", + "onlySpeakDisplayedText", + "speechServerFactory", + "speechServerInfo", + "voices", + "speechVerbosityLevel", + "readFullRowInGUITable", + "readFullRowInDocumentTable", + "readFullRowInSpreadSheet", + "enableSpeechIndentation", + "enableEchoByCharacter", + "enableEchoByWord", + "enableEchoBySentence", + "enableKeyEcho", + "enableAlphabeticKeys", + "enableNumericKeys", + "enablePunctuationKeys", + "enableSpace", + "enableModifierKeys", + "enableFunctionKeys", + "enableActionKeys", + "enableNavigationKeys", + "enableDiacriticalKeys", + "enablePauseBreaks", + "enableTutorialMessages", + "enableMnemonicSpeaking", + "enablePositionSpeaking", + "enableBraille", + "enableBrailleContext", + "disableBrailleEOL", + "brailleVerbosityLevel", + "brailleRolenameStyle", + "brailleSelectorIndicator", + "brailleLinkIndicator", + "enableSound", + "soundVolume", + "playSoundForRole", + "playSoundForState", + "playSoundForPositionInSet", + "playSoundForValue", + "verbalizePunctuationStyle", + "presentToolTips", + "sayAllStyle", + "keyboardLayout", + "speakBlankLines", + "speakMultiCaseStringsAsWords", + "speakNumbersAsDigits", + "speakMisspelledIndicator", + "enabledSpokenTextAttributes", + "enabledBrailledTextAttributes", + "textAttributesBrailleIndicator", + "profile", + "speakProgressBarUpdates", + "brailleProgressBarUpdates", + "beepProgressBarUpdates", + "progressBarUpdateInterval", + "progressBarVerbosity", + "ignoreStatusBarProgressBars", + "enableBrailleWordWrap", + "enableContractedBraille", + "brailleContractionTable", + "enableMouseReview", + "speakCellCoordinates", + "speakSpreadsheetCoordinates", + "alwaysSpeakSelectedSpreadsheetRange", + "speakCellSpan", + "speakCellHeaders", + "skipBlankCells", + "largeObjectTextLength", + "structuralNavigationEnabled", + "wrappedStructuralNavigation", + "chatMessageVerbosity", + "chatSpeakRoomName", + "chatAnnounceBuddyTyping", + "chatRoomHistories", + "enableFlashMessages", + "brailleFlashTime", + "flashIsPersistent", + "flashIsDetailed", + "messagesAreDetailed", + "presentDateFormat", + "presentTimeFormat", + "activeProfile", + "activePlugins", + "startingProfile", + "spellcheckSpellError", + "spellcheckSpellSuggestion", + "spellcheckPresentContext", + "useColorNames", + "capitalizationStyle", + "findResultsVerbosity", + "findResultsMinimumLength", + "structNavTriggersFocusMode", + "caretNavTriggersFocusMode", + "layoutMode", + "nativeNavTriggersFocusMode", + "rewindAndFastForwardInSayAll", + "structNavInSayAll", + "speakDescription", + "speakContextBlockquote", + "speakContextPanel", + "speakContextLandmark", + "speakContextNonLandmarkForm", + "speakContextList", + "speakContextTable", + "sayAllContextBlockquote", + "sayAllContextPanel", + "sayAllContextLandmark", + "sayAllContextNonLandmarkForm", + "sayAllContextList", + "sayAllContextTable", + "aiAssistantEnabled", + "aiProvider", + "aiApiKeyFile", + "aiOllamaModel", + "aiOllamaEndpoint", + "aiConfirmationRequired", + "aiActionTimeout", + "aiScreenshotQuality", + "aiMaxContextLength" +] + +GENERAL_KEYBOARD_LAYOUT_DESKTOP = 1 +GENERAL_KEYBOARD_LAYOUT_LAPTOP = 2 + +DESKTOP_MODIFIER_KEYS = ["Insert", "KP_Insert"] +LAPTOP_MODIFIER_KEYS = ["Caps_Lock", "Shift_Lock"] + +VERBOSITY_LEVEL_BRIEF = 0 +VERBOSITY_LEVEL_VERBOSE = 1 + +BRAILLE_UNDERLINE_NONE = 0x00 # 00000000 +BRAILLE_UNDERLINE_7 = 0x40 # 01000000 +BRAILLE_UNDERLINE_8 = 0x80 # 10000000 +BRAILLE_UNDERLINE_BOTH = 0xc0 # 11000000 + +BRAILLE_ROLENAME_STYLE_SHORT = 0 # three letter abbreviations +BRAILLE_ROLENAME_STYLE_LONG = 1 # full rolename + +PUNCTUATION_STYLE_NONE = 3 +PUNCTUATION_STYLE_SOME = 2 +PUNCTUATION_STYLE_MOST = 1 +PUNCTUATION_STYLE_ALL = 0 + +CAPITALIZATION_STYLE_NONE = "none" +CAPITALIZATION_STYLE_SPELL = "spell" +CAPITALIZATION_STYLE_ICON = "icon" + +SAYALL_STYLE_LINE = 0 +SAYALL_STYLE_SENTENCE = 1 + +PROGRESS_BAR_ALL = 0 +PROGRESS_BAR_APPLICATION = 1 +PROGRESS_BAR_WINDOW = 2 + +CHAT_SPEAK_ALL = 0 +CHAT_SPEAK_ALL_IF_FOCUSED = 1 +CHAT_SPEAK_FOCUSED_CHANNEL = 2 + +# AI Assistant constants +AI_PROVIDER_CLAUDE = "claude" +AI_PROVIDER_CLAUDE_CODE = "claude_code" +AI_PROVIDER_CHATGPT = "chatgpt" +AI_PROVIDER_GEMINI = "gemini" +AI_PROVIDER_OLLAMA = "ollama" + +AI_SCREENSHOT_QUALITY_LOW = "low" +AI_SCREENSHOT_QUALITY_MEDIUM = "medium" +AI_SCREENSHOT_QUALITY_HIGH = "high" + +DEFAULT_VOICE = "default" +UPPERCASE_VOICE = "uppercase" +HYPERLINK_VOICE = "hyperlink" +SYSTEM_VOICE = "system" + +voicesKeys = { +"DEFAULT_VOICE" : "default", +"UPPERCASE_VOICE" : "uppercase", +"HYPERLINK_VOICE" : "hyperlink", +"SYSTEM_VOICE" : "system" +} + + +voices = { + DEFAULT_VOICE: ACSS({}), + UPPERCASE_VOICE: ACSS({ACSS.AVERAGE_PITCH : 7.0}), + HYPERLINK_VOICE: ACSS({}), + SYSTEM_VOICE: ACSS({}), +} + +# Profiles +startingProfile = ['Default', 'default'] +activeProfile = ['Default', 'default'] +profile = ['Default', 'default'] + +# Speech +speechFactoryModules = ["speechdispatcherfactory"] +speechServerFactory = "speechdispatcherfactory" +speechServerInfo = None # None means let the factory decide. +enableSpeech = True +silenceSpeech = False +enableTutorialMessages = False +enableMnemonicSpeaking = False +enablePositionSpeaking = False +enableSpeechIndentation = False +onlySpeakDisplayedText = False +presentToolTips = False +speakBlankLines = True +repeatCharacterLimit = 4 +readFullRowInGUITable = True +readFullRowInDocumentTable = True +readFullRowInSpreadSheet = False +speakCellCoordinates = True +speakCellSpan = True +speakCellHeaders = True +speakSpreadsheetCoordinates = True +alwaysSpeakSelectedSpreadsheetRange = False +speakMultiCaseStringsAsWords = False +speakNumbersAsDigits = False +speakMisspelledIndicator = True +useColorNames = True +usePronunciationDictionary = True +sayAllStyle = SAYALL_STYLE_SENTENCE +capitalizationStyle = CAPITALIZATION_STYLE_NONE +verbalizePunctuationStyle = PUNCTUATION_STYLE_MOST +speechVerbosityLevel = VERBOSITY_LEVEL_VERBOSE +messagesAreDetailed = True +enablePauseBreaks = True +speakDescription = True +speakContextBlockquote = True +speakContextPanel = True +speakContextNonLandmarkForm = True +speakContextLandmark = True +speakContextList = True +speakContextTable = True +sayAllContextBlockquote = True +sayAllContextPanel = True +sayAllContextNonLandmarkForm = True +sayAllContextLandmark = True +sayAllContextList = True +sayAllContextTable = True + +# Braille +enableBraille = True +enableBrailleMonitor = False +enableBrailleContext = True +enableFlashMessages = True +brailleFlashTime = 5000 +flashIsPersistent = False +flashIsDetailed = True +enableBrailleWordWrap = False +enableContractedBraille = False +brailleContractionTable = '' +disableBrailleEOL = False +brailleRolenameStyle = BRAILLE_ROLENAME_STYLE_LONG +brailleSelectorIndicator = BRAILLE_UNDERLINE_BOTH +brailleLinkIndicator = BRAILLE_UNDERLINE_BOTH +textAttributesBrailleIndicator = BRAILLE_UNDERLINE_NONE +brailleVerbosityLevel = VERBOSITY_LEVEL_VERBOSE + +# Sound +enableSound = True +soundVolume = 0.5 +playSoundForRole = False +playSoundForState = False +playSoundForPositionInSet = False +playSoundForValue = False + +# Keyboard and Echo +keyboardLayout = GENERAL_KEYBOARD_LAYOUT_DESKTOP +cthulhuModifierKeys = DESKTOP_MODIFIER_KEYS +doubleClickTimeout = 0.5 +enableKeyEcho = True +enableAlphabeticKeys = True +enableNumericKeys = True +enablePunctuationKeys = True +enableSpace = True +enableModifierKeys = True +enableFunctionKeys = True +enableActionKeys = True +enableNavigationKeys = False +enableDiacriticalKeys = False +enableEchoByCharacter = False +enableEchoByWord = False +enableEchoBySentence = False +presentLockingKeys = None + +# Mouse review +enableMouseReview = False + +# Flat review +flatReviewIsRestricted = False + +# Progressbars +speakProgressBarUpdates = True +brailleProgressBarUpdates = False +beepProgressBarUpdates = False +progressBarUpdateInterval = 10 +progressBarSpeechInterval = None +progressBarBrailleInterval = None +progressBarBeepInterval = 0 +progressBarVerbosity = PROGRESS_BAR_APPLICATION +ignoreStatusBarProgressBars = True + +# Structural navigation +structuralNavigationEnabled = True +skipBlankCells = False +largeObjectTextLength = 75 +wrappedStructuralNavigation = True +inferLiveRegions = True + +# Chat +chatMessageVerbosity = CHAT_SPEAK_ALL +chatSpeakRoomName = False +chatAnnounceBuddyTyping = False +chatRoomHistories = False + +# Spellcheck +spellcheckSpellError = True +spellcheckSpellSuggestion = True +spellcheckPresentContext = True + +# Day and time +presentDateFormat = messages.DATE_FORMAT_LOCALE +presentTimeFormat = messages.TIME_FORMAT_LOCALE + +# App search support +FIND_SPEAK_NONE = 0 +FIND_SPEAK_IF_LINE_CHANGED = 1 +FIND_SPEAK_ALL = 2 +findResultsVerbosity = FIND_SPEAK_ALL +findResultsMinimumLength = 4 + +# The complete list of possible text attributes. +allTextAttributes = \ + "bg-color:; bg-full-height:; bg-stipple:; direction:; editable:; " \ + "family-name:; fg-color:; fg-stipple:; font-effect:none; indent:0; " \ + "invisible:; justification:left; language:; left-margin:; " \ + "line-height:100%; paragraph-style:Default; pixels-above-lines:; " \ + "pixels-below-lines:; pixels-inside-wrap:; right-margin:; rise:; " \ + "scale:; size:; stretch:; strikethrough:false; style:normal; " \ + "text-decoration:none; text-rotation:0; text-shadow:none; " \ + "text-spelling:none; underline:none; variant:; " \ + "vertical-align:baseline; weight:400; wrap-mode:; writing-mode:lr-tb;" + +# The default set of text attributes to speak to the user. Specific +# application scripts (or individual users can override these values if +# so desired. Each of these text attributes is of the form :; +# The part will be the "default" value for that attribute. In +# other words, if the attribute for a given piece of text has that value, +# it won't be spoken. If no value part is given, then that attribute will +# always be spoken. +enabledSpokenTextAttributes = \ + "size:; family-name:; weight:400; indent:0; underline:none; " \ + "strikethrough:false; justification:left; style:normal; " \ + "paragraph-style:; text-spelling:none; fg-color:; bg-color:;" + +# The default set of text attributes to be brailled for the user. Specific +# application scripts (or individual users can override these values if +# so desired. Each of these text attributes is of the form :; +# The part will be the "default" value for that attribute. In +# other words, if the attribute for a given piece of text has that value, +# it won't be spoken. If no value part is given, then that attribute will +# always be brailled. +enabledBrailledTextAttributes = \ + "size:; family-name:; weight:400; indent:0; underline:none; " \ + "strikethrough:false; justification:left; style:normal; " \ + "text-spelling:none;" + +# Latent support to allow the user to override/define keybindings +# and braille bindings. Unsupported and undocumented for now. +# Use at your own risk. +# +keyBindingsMap = {} +brailleBindingsMap = {} + +# TODO - JD: Is this still needed now that AT-SPI has its own timeout? +timeoutTime = 10 # a value of 0 means don't do hang checking +timeoutCallback = None # Set by cthulhu.py:init to cthulhu.timeout + +structNavTriggersFocusMode = False +caretNavTriggersFocusMode = False +nativeNavTriggersFocusMode = True + +layoutMode = True + +rewindAndFastForwardInSayAll = False +structNavInSayAll = False + +# N.B. The following are experimental and may change or go away at any time. +enableSadPidginHack = False +presentChatRoomLast = False +presentLiveRegionFromInactiveTab = False + +# Plugins +activePlugins = ['AIAssistant', 'DisplayVersion', 'PluginManager', 'HelloCthulhu', 'ByeCthulhu'] + +# AI Assistant settings (disabled by default for opt-in behavior) +aiAssistantEnabled = True +aiProvider = AI_PROVIDER_CLAUDE_CODE +aiApiKeyFile = "" +aiOllamaModel = "llama3.2-vision" +aiOllamaEndpoint = "http://localhost:11434" +aiConfirmationRequired = True +aiActionTimeout = 30 +aiScreenshotQuality = AI_SCREENSHOT_QUALITY_MEDIUM +aiMaxContextLength = 4000 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings_manager.py new file mode 100644 index 0000000..46ab9f7 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/settings_manager.py @@ -0,0 +1,682 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Settings manager module. This will load/save user settings from a +defined settings backend.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios." +__license__ = "LGPL" + +import importlib +import os +from gi.repository import Gio, GLib + +from . import debug +from . import cthulhu_i18n +from . import script_manager +from . import settings +from . import pronunciation_dict +from .acss import ACSS +from .ax_object import AXObject +from .keybindings import KeyBinding + +try: + _proxy = Gio.DBusProxy.new_for_bus_sync( + Gio.BusType.SESSION, + Gio.DBusProxyFlags.NONE, + None, + 'org.a11y.Bus', + '/org/a11y/bus', + 'org.freedesktop.DBus.Properties', + None) +except Exception: + _proxy = None + +_scriptManager = script_manager.getManager() + +class SettingsManager(object): + """Settings backend manager. This class manages cthulhu user's settings + using different backends""" + _instance = None + + def __new__(cls, *args, **kwargs): + if '__instance' not in vars(cls): + cls.__instance = object.__new__(cls, *args, **kwargs) + return cls.__instance + + def __init__(self, backend='json'): + """Initialize a SettingsManager Object. + If backend isn't defined then uses default backend, in this + case json-backend. + backend parameter can use the follow values: + backend='json' + """ + + debug.printMessage(debug.LEVEL_INFO, 'SETTINGS MANAGER: Initializing', True) + + self.backendModule = None + self._backend = None + self.profile = None + self.backendName = backend + self._prefsDir = None + + # Dictionaries for store the default values + # The keys and values are defined at cthulhu.settings + # + self.defaultGeneral = {} + self.defaultPronunciations = {} + self.defaultKeybindings = {} + + # Dictionaries that store the key:value pairs which values are + # different from the current profile and the default ones + # + self.profileGeneral = {} + self.profilePronunciations = {} + self.profileKeybindings = {} + + # Dictionaries that store the current settings. + # They are result to overwrite the default values with + # the ones from the current active profile + self.general = {} + self.pronunciations = {} + self.keybindings = {} + + self._activeApp = "" + self._appGeneral = {} + self._appPronunciations = {} + self._appKeybindings = {} + + if not self._loadBackend(): + raise Exception('SettingsManager._loadBackend failed.') + + self.customizedSettings = {} + self._customizationCompleted = False + + # For handling the currently-"classic" application settings + self.settingsPackages = ["app-settings"] + + debug.printMessage(debug.LEVEL_INFO, 'SETTINGS MANAGER: Initialized', True) + + def activate(self, prefsDir=None, customSettings={}): + debug.printMessage(debug.LEVEL_INFO, 'SETTINGS MANAGER: Activating', True) + + self.customizedSettings.update(customSettings) + self._prefsDir = prefsDir \ + or os.path.join(GLib.get_user_data_dir(), "cthulhu") + + # Load the backend and the default values + self._backend = self.backendModule.Backend(self._prefsDir) + self._setDefaultGeneral() + self._setDefaultPronunciations() + self._setDefaultKeybindings() + self.general = self.defaultGeneral.copy() + if not self.isFirstStart(): + self.general.update(self._backend.getGeneral()) + self.pronunciations = self.defaultPronunciations.copy() + self.keybindings = self.defaultKeybindings.copy() + + # If this is the first time we launch Cthulhu, there is no user settings + # yet, so we need to create the user config directories and store the + # initial default settings + # + self._createDefaults() + + debug.printMessage(debug.LEVEL_INFO, 'SETTINGS MANAGER: Activated', True) + + # Set the active profile and load its stored settings + tokens = ["SETTINGS MANAGER: Current profile is", self.profile] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if self.profile is None: + self.profile = self.general.get('startingProfile')[1] + tokens = ["SETTINGS MANAGER: Current profile is now", self.profile] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self.setProfile(self.profile) + + def _loadBackend(self): + """Load specific backend for manage user settings""" + + try: + backend = f'.backends.{self.backendName}_backend' + self.backendModule = importlib.import_module(backend, 'cthulhu') + return True + except Exception: + return False + + def _createDefaults(self): + """Let the active backend to create the initial structure + for storing the settings and save the default ones from + cthulhu.settings""" + def _createDir(dirName): + if not os.path.isdir(dirName): + os.makedirs(dirName) + + # Set up the user's preferences directory + # ($XDG_DATA_HOME/cthulhu by default). + # + cthulhuDir = self._prefsDir + _createDir(cthulhuDir) + + # Set up $XDG_DATA_HOME/cthulhu/cthulhu-scripts as a Python package + # + cthulhuScriptDir = os.path.join(cthulhuDir, "cthulhu-scripts") + _createDir(cthulhuScriptDir) + initFile = os.path.join(cthulhuScriptDir, "__init__.py") + if not os.path.exists(initFile): + os.close(os.open(initFile, os.O_CREAT, 0o700)) + + cthulhuSettingsDir = os.path.join(cthulhuDir, "app-settings") + _createDir(cthulhuSettingsDir) + + cthulhuSoundsDir = os.path.join(cthulhuDir, "sounds") + _createDir(cthulhuSoundsDir) + + # Set up $XDG_DATA_HOME/cthulhu/cthulhu-customizations.py empty file and + # define cthulhuDir as a Python package. + initFile = os.path.join(cthulhuDir, "__init__.py") + if not os.path.exists(initFile): + os.close(os.open(initFile, os.O_CREAT, 0o700)) + + userCustomFile = os.path.join(cthulhuDir, "cthulhu-customizations.py") + if not os.path.exists(userCustomFile): + os.close(os.open(userCustomFile, os.O_CREAT, 0o700)) + + if self.isFirstStart(): + self._backend.saveDefaultSettings(self.defaultGeneral, + self.defaultPronunciations, + self.defaultKeybindings) + + def _setDefaultPronunciations(self): + """Get the pronunciations by default from cthulhu.settings""" + self.defaultPronunciations = {} + + def _setDefaultKeybindings(self): + """Get the keybindings by default from cthulhu.settings""" + self.defaultKeybindings = {} + + def _setDefaultGeneral(self): + """Get the general settings by default from cthulhu.settings""" + self._getCustomizedSettings() + self.defaultGeneral = {} + for key in settings.userCustomizableSettings: + value = self.customizedSettings.get(key) + if value is None: + try: + value = getattr(settings, key) + except Exception: + pass + self.defaultGeneral[key] = value + + def _getCustomizedSettings(self): + if self._customizationCompleted: + return self.customizedSettings + + originalSettings = {} + for key, value in settings.__dict__.items(): + originalSettings[key] = value + + self._customizationCompleted = self._loadUserCustomizations() + + for key, value in originalSettings.items(): + customValue = settings.__dict__.get(key) + if value != customValue: + self.customizedSettings[key] = customValue + + def _loadUserCustomizations(self): + """Attempt to load the user's cthulhu-customizations. Returns a boolean + indicating our success at doing so, where success is measured by the + likelihood that the results won't be different if we keep trying.""" + + success = False + pathList = [self._prefsDir] + tokens = ["SETTINGS MANAGER: Attempt to load cthulhu-customizations"] + module_path = pathList[0] + "/cthulhu-customizations.py" + + try: + spec = importlib.util.spec_from_file_location("cthulhu-customizations", module_path) + if spec is not None: + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + tokens.extend(["from", module_path, "succeeded."]) + success = True + else: + tokens.extend(["from", module_path, "failed. Spec not found."]) + except FileNotFoundError: + tokens.extend(["from", module_path, "failed. File not found."]) + except Exception as error: + # Treat this failure as a "success" so that we don't stomp on the existing file. + success = True + tokens.extend(["failed due to:", error, ". Not loading customizations."]) + + debug.printTokens(debug.LEVEL_ALL, tokens, True) + return success + + def getPrefsDir(self): + return self._prefsDir + + def setSetting(self, settingName, settingValue): + self._setSettingsRuntime({settingName:settingValue}) + + def getSetting(self, settingName): + return getattr(settings, settingName, None) + + def getVoiceLocale(self, voice='default'): + voices = self.getSetting('voices') + v = ACSS(voices.get(voice, {})) + lang = v.getLocale() + dialect = v.getDialect() + if dialect and len(str(dialect)) == 2: + lang = f"{lang}_{dialect.upper()}" + return lang + + def getSpeechServerFactories(self): + """Imports all known SpeechServer factory modules.""" + + factories = [] + for moduleName in self.getSetting('speechFactoryModules'): + try: + module = importlib.import_module(f'cthulhu.{moduleName}') + factories.append(module) + tokens = ["SETTINGS MANAGER: Valid speech server factory:", moduleName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + except Exception: + tokens = ["SETTINGS MANAGER: Invalid speech server factory:", moduleName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + return factories + + def _loadProfileSettings(self, profile=None): + """Get from the active backend all the settings for the current + profile and store them in the object's attributes. + A profile can be passed as a parameter. This could be useful for + change from one profile to another.""" + + tokens = ["SETTINGS MANAGER: Loading settings for", profile, "profile"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if profile is None: + profile = self.profile + self.profileGeneral = self.getGeneralSettings(profile) or {} + self.profilePronunciations = self.getPronunciations(profile) or {} + self.profileKeybindings = self.getKeybindings(profile) or {} + + tokens = ["SETTINGS MANAGER: Settings for", profile, "profile loaded"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def _mergeSettings(self): + """Update the changed values on the profile settings + over the current and active settings""" + + msg = 'SETTINGS MANAGER: Merging settings.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.profileGeneral.update(self._appGeneral) + self.profilePronunciations.update(self._appPronunciations) + self.profileKeybindings.update(self._appKeybindings) + + self.general.update(self.profileGeneral) + self.pronunciations.update(self.profilePronunciations) + self.keybindings.update(self.profileKeybindings) + + msg = 'SETTINGS MANAGER: Settings merged.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _enableAccessibility(self): + """Enables the GNOME accessibility flag. Users need to log out and + then back in for this to take effect. + + Returns True if an action was taken (i.e., accessibility was not + set prior to this call). + """ + + alreadyEnabled = self.isAccessibilityEnabled() + if not alreadyEnabled: + self.setAccessibility(True) + + return not alreadyEnabled + + def isAccessibilityEnabled(self): + msg = 'SETTINGS MANAGER: Checking if accessibility is enabled.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + msg = 'SETTINGS MANAGER: Accessibility enabled: ' + if not _proxy: + rv = False + msg += 'Error (no proxy)' + else: + rv = _proxy.Get('(ss)', 'org.a11y.Status', 'IsEnabled') + msg += str(rv) + + debug.printMessage(debug.LEVEL_INFO, msg, True) + return rv + + def setAccessibility(self, enable): + msg = f'SETTINGS MANAGER: Attempting to set accessibility to {enable}.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not _proxy: + msg = 'SETTINGS MANAGER: Error (no proxy)' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + vEnable = GLib.Variant('b', enable) + _proxy.Set('(ssv)', 'org.a11y.Status', 'IsEnabled', vEnable) + + msg = f'SETTINGS MANAGER: Finished setting accessibility to {enable}.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def isScreenReaderServiceEnabled(self): + """Returns True if the screen reader service is enabled. Note that + this does not necessarily mean that Cthulhu (or any other screen reader) + is running at the moment.""" + + msg = 'SETTINGS MANAGER: Is screen reader service enabled? ' + + if not _proxy: + rv = False + msg += 'Error (no proxy)' + else: + rv = _proxy.Get('(ss)', 'org.a11y.Status', 'ScreenReaderEnabled') + msg += str(rv) + + debug.printMessage(debug.LEVEL_INFO, msg, True) + return rv + + def setStartingProfile(self, profile=None): + if profile is None: + profile = settings.profile + self._backend._setProfileKey('startingProfile', profile) + + def getProfile(self): + return self.profile + + def setProfile(self, profile='default', updateLocale=False): + """Set a specific profile as the active one. + Also the settings from that profile will be loading + and updated the current settings with them.""" + + tokens = ["SETTINGS MANAGER: Setting profile to:", profile] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + oldVoiceLocale = self.getVoiceLocale('default') + self.profile = profile + self._loadProfileSettings(profile) + self._mergeSettings() + self._setSettingsRuntime(self.general) + + if not updateLocale: + return + + newVoiceLocale = self.getVoiceLocale('default') + if oldVoiceLocale != newVoiceLocale: + cthulhu_i18n.setLocaleForNames(newVoiceLocale) + cthulhu_i18n.setLocaleForMessages(newVoiceLocale) + cthulhu_i18n.setLocaleForGUI(newVoiceLocale) + + tokens = ["SETTINGS MANAGER: Profile set to:", profile] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def removeProfile(self, profile): + self._backend.removeProfile(profile) + + def _setSettingsRuntime(self, settingsDict): + msg = 'SETTINGS MANAGER: Setting runtime settings.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + for key, value in settingsDict.items(): + setattr(settings, str(key), value) + self._getCustomizedSettings() + for key, value in self.customizedSettings.items(): + setattr(settings, str(key), value) + + msg = 'SETTINGS MANAGER: Runtime settings set.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _setPronunciationsRuntime(self, pronunciationsDict): + pronunciation_dict.pronunciation_dict = {} + for key, value in pronunciationsDict.values(): + if key and value: + pronunciation_dict.setPronunciation(key, value) + + def getGeneralSettings(self, profile='default'): + """Return the current general settings. + Those settings comes from updating the default settings + with the profiles' ones""" + return self._backend.getGeneral(profile) + + def getPronunciations(self, profile='default'): + """Return the current pronunciations settings. + Those settings comes from updating the default settings + with the profiles' ones""" + return self._backend.getPronunciations(profile) + + def getKeybindings(self, profile='default'): + """Return the current keybindings settings. + Those settings comes from updating the default settings + with the profiles' ones""" + return self._backend.getKeybindings(profile) + + def _setProfileGeneral(self, general): + """Set the changed general settings from the defaults' ones + as the profile's.""" + + msg = 'SETTINGS MANAGER: Setting general settings for profile' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.profileGeneral = {} + + for key, value in general.items(): + if key in ['startingProfile', 'activeProfile']: + continue + elif key == 'profile': + self.profileGeneral[key] = value + elif value != self.defaultGeneral.get(key): + self.profileGeneral[key] = value + elif self.general.get(key) != value: + self.profileGeneral[key] = value + + msg = 'SETTINGS MANAGER: General settings for profile set' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _setProfilePronunciations(self, pronunciations): + """Set the changed pronunciations settings from the defaults' ones + as the profile's.""" + + msg = 'SETTINGS MANAGER: Setting pronunciation settings for profile.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.profilePronunciations = self.defaultPronunciations.copy() + self.profilePronunciations.update(pronunciations) + + msg = 'SETTINGS MANAGER: Pronunciation settings for profile set.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _setProfileKeybindings(self, keybindings): + """Set the changed keybindings settings from the defaults' ones + as the profile's.""" + + msg = 'SETTINGS MANAGER: Setting keybindings settings for profile.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + self.profileKeybindings = self.defaultKeybindings.copy() + self.profileKeybindings.update(keybindings) + + msg = 'SETTINGS MANAGER: Keybindings settings for profile set.' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _saveAppSettings(self, appName, general, pronunciations, keybindings): + appGeneral = {} + profileGeneral = self.getGeneralSettings(self.profile) + for key, value in general.items(): + if value != profileGeneral.get(key): + appGeneral[key] = value + + appPronunciations = {} + profilePronunciations = self.getPronunciations(self.profile) + for key, value in pronunciations.items(): + if value != profilePronunciations.get(key): + appPronunciations[key] = value + + appKeybindings = {} + profileKeybindings = self.getKeybindings(self.profile) + for key, value in keybindings.items(): + if value != profileKeybindings.get(key): + appKeybindings[key] = value + + self._backend.saveAppSettings(appName, + self.profile, + appGeneral, + appPronunciations, + appKeybindings) + + def saveSettings(self, script, general, pronunciations, keybindings): + """Save the settings provided for the script provided.""" + + tokens = ["SETTINGS MANAGER: Saving settings for", script, "(app:", script.app, ")"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + app = script.app + if app: + self._saveAppSettings(AXObject.get_name(app), general, pronunciations, keybindings) + return + + # Assign current profile + _profile = general.get('profile', settings.profile) + currentProfile = _profile[1] + + self.profile = currentProfile + + # Elements that need to stay updated in main configuration. + self.defaultGeneral['startingProfile'] = general.get('startingProfile', + _profile) + + self._setProfileGeneral(general) + self._setProfilePronunciations(pronunciations) + self._setProfileKeybindings(keybindings) + + tokens = ["SETTINGS MANAGER: Saving for backend", self._backend] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self._backend.saveProfileSettings(self.profile, + self.profileGeneral, + self.profilePronunciations, + self.profileKeybindings) + + tokens = ["SETTINGS MANAGER: Settings for", script, "(app:", script.app, ") saved"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return self._enableAccessibility() + + def _adjustBindingTupleValues(self, bindingTuple): + """Converts the values of bindingTuple into KeyBinding-ready values.""" + + keysym, mask, mods, clicks = bindingTuple + if not keysym: + bindingTuple = ('', 0, 0, 0) + else: + bindingTuple = (keysym, int(mask), int(mods), int(clicks)) + + return bindingTuple + + def overrideKeyBindings(self, script, scriptKeyBindings): + keybindingsSettings = self.profileKeybindings + for handlerString, bindingTuples in keybindingsSettings.items(): + handler = script.inputEventHandlers.get(handlerString) + if not handler: + continue + + scriptKeyBindings.removeByHandler(handler) + for bindingTuple in bindingTuples: + bindingTuple = self._adjustBindingTupleValues(bindingTuple) + keysym, mask, mods, clicks = bindingTuple + newBinding = KeyBinding(keysym, mask, mods, handler, clicks) + scriptKeyBindings.add(newBinding) + + return scriptKeyBindings + + def isFirstStart(self): + """Check if the firstStart key is True or false""" + return self._backend.isFirstStart() + + def setFirstStart(self, value=False): + """Set firstStart. This user-configurable setting is primarily + intended to serve as an indication as to whether or not initial + configuration is needed.""" + self._backend.setFirstStart(value) + + def availableProfiles(self): + """Get available profiles from active backend""" + + return self._backend.availableProfiles() + + def getAppSetting(self, app, settingName, fallbackOnDefault=True): + if not app: + return None + + appPrefs = self._backend.getAppSettings(AXObject.get_name(app)) + profiles = appPrefs.get('profiles', {}) + profilePrefs = profiles.get(self.profile, {}) + general = profilePrefs.get('general', {}) + appSetting = general.get(settingName) + if appSetting is None and fallbackOnDefault: + general = self._backend.getGeneral(self.profile) + appSetting = general.get(settingName) + + return appSetting + + def loadAppSettings(self, script): + """Load the users application specific settings for an app. + + Arguments: + - script: the current active script. + """ + + if not (script and script.app): + return + + for key in self._appPronunciations.keys(): + self.pronunciations.pop(key) + + prefs = self._backend.getAppSettings(AXObject.get_name(script.app)) + profiles = prefs.get('profiles', {}) + profilePrefs = profiles.get(self.profile, {}) + + self._appGeneral = profilePrefs.get('general', {}) + self._appKeybindings = profilePrefs.get('keybindings', {}) + self._appPronunciations = profilePrefs.get('pronunciations', {}) + self._activeApp = AXObject.get_name(script.app) + + self._loadProfileSettings() + self._mergeSettings() + self._setSettingsRuntime(self.general) + self._setPronunciationsRuntime(self.pronunciations) + script.keyBindings = self.overrideKeyBindings(script, script.getKeyBindings()) + +_manager = SettingsManager() + +def getManager(): + return _manager diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/signal_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/signal_manager.py new file mode 100644 index 0000000..72e3dce --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/signal_manager.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import gi +from gi.repository import GObject + +from cthulhu import resource_manager + +class SignalManager(): + def __init__(self, app): + self.app = app + self.resourceManager = self.app.getResourceManager() + + def registerSignal(self, signalName, signalFlag = GObject.SignalFlags.RUN_LAST, closure = GObject.TYPE_NONE, accumulator=(), contextName = None): + # register signal + ok = False + if not self.signalExist(signalName): + GObject.signal_new(signalName, self.app, signalFlag, closure,accumulator) + ok = True + resourceContext = self.resourceManager.getResourceContext(contextName) + if resourceContext: + resourceEntry = resource_manager.ResourceEntry('signal', signalName, signalName, signalName, signalName) + resourceContext.addSignal(signalName, resourceEntry) + return ok + + def signalExist(self, signalName): + return GObject.signal_lookup(signalName, self.app) != 0 + def connectSignal(self, signalName, function, profile, param = None, contextName = None): + signalID = None + try: + if self.signalExist(signalName): + tryFunction = resource_manager.TryFunction(function) + signalID = self.app.connect(signalName, tryFunction.runSignal) + resourceContext = self.resourceManager.getResourceContext(contextName) + if resourceContext: + resourceEntry = resource_manager.ResourceEntry('subscription', signalID, function, tryFunction, signalName) + resourceContext.addSubscription(signalName, function, resourceEntry) + else: + print('signal {} does not exist'.format(signalName)) + except Exception as e: + print(e) + + return signalID + def disconnectSignalByFunction(self, function, contextName = None): + ok = False + try: + self.app.disconnect_by_func(function) + ok = True + except: + pass + resourceContext = self.resourceManager.getResourceContext(contextName) + if resourceContext: + resourceContext.removeSubscriptionByFunction(function) + return ok + def emitSignal(self, signalName): + # emit an signal + try: + self.app.emit(signalName) + print('after Emit Signal: {}'.format(signalName)) + except: + print('Signal "{}" does not exist.'.format(signalName)) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound.py new file mode 100644 index 0000000..c435aa2 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for playing sounds.""" + +__id__ = "$Id:$" +__version__ = "$Revision:$" +__date__ = "$Date:$" +__copyright__ = "Copyright (c) 2016 Cthulhu Team" +__license__ = "LGPL" + +import gi +from gi.repository import GLib + +try: + gi.require_version('Gst', '1.0') + from gi.repository import Gst +except Exception: + _gstreamerAvailable = False +else: + _gstreamerAvailable, args = Gst.init_check(None) + +from . import debug +from .sound_generator import Icon, Tone + +class Player: + """Plays Icons and Tones.""" + + def __init__(self): + self._initialized = False + self._source = None + self._sink = None + self._player = None + self._pipeline = None + + if not _gstreamerAvailable: + msg = 'SOUND ERROR: Gstreamer is not available' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + self.init() + + def _onPlayerMessage(self, bus, message): + if message.type == Gst.MessageType.EOS: + self._player.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._player.set_state(Gst.State.NULL) + error, info = message.parse_error() + msg = f'SOUND ERROR: {error}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _onPipelineMessage(self, bus, message): + if message.type == Gst.MessageType.EOS: + self._pipeline.set_state(Gst.State.NULL) + elif message.type == Gst.MessageType.ERROR: + self._pipeline.set_state(Gst.State.NULL) + error, info = message.parse_error() + msg = f'SOUND ERROR: {error}' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _onTimeout(self, element): + element.set_state(Gst.State.NULL) + return False + + def _playIcon(self, icon, interrupt=True): + """Plays a sound icon, interrupting the current play first unless specified.""" + + if interrupt: + self._player.set_state(Gst.State.NULL) + + self._player.set_property('uri', f'file://{icon.path}') + self._player.set_state(Gst.State.PLAYING) + + def _playTone(self, tone, interrupt=True): + """Plays a tone, interrupting the current play first unless specified.""" + + if interrupt: + self._pipeline.set_state(Gst.State.NULL) + + self._source.set_property('volume', tone.volume) + self._source.set_property('freq', tone.frequency) + self._source.set_property('wave', tone.wave) + self._pipeline.set_state(Gst.State.PLAYING) + duration = int(1000 * tone.duration) + GLib.timeout_add(duration, self._onTimeout, self._pipeline) + + def init(self): + """(Re)Initializes the Player.""" + + if self._initialized: + return + + if not _gstreamerAvailable: + return + + self._player = Gst.ElementFactory.make('playbin', 'player') + if self._player is None: + msg = 'SOUND ERROR: Gstreamer is available, but player is None' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPlayerMessage) + + self._pipeline = Gst.Pipeline(name='cthulhu-pipeline') + bus = self._pipeline.get_bus() + bus.add_signal_watch() + bus.connect("message", self._onPipelineMessage) + + self._source = Gst.ElementFactory.make('audiotestsrc', 'src') + self._sink = Gst.ElementFactory.make('autoaudiosink', 'output') + if self._source is None or self._sink is None: + return + + self._pipeline.add(self._source) + self._pipeline.add(self._sink) + self._source.link(self._sink) + + self._initialized = True + + def play(self, item, interrupt=True): + """Plays a sound, interrupting the current play first unless specified.""" + + if isinstance(item, Icon): + self._playIcon(item, interrupt) + elif isinstance(item, Tone): + self._playTone(item, interrupt) + else: + tokens = ["SOUND ERROR:", item, "is not an Icon or Tone"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + def stop(self, element=None): + """Stops play.""" + + if not _gstreamerAvailable: + return + + if element: + element.set_state(Gst.State.NULL) + return + + if self._player: + self._player.set_state(Gst.State.NULL) + + if self._pipeline: + self._pipeline.set_state(Gst.State.NULL) + + def shutdown(self): + """Shuts down the sound utilities.""" + + global _gstreamerAvailable + if not _gstreamerAvailable: + return + + self.stop() + self._initialized = False + _gstreamerAvailable = False + +_player = Player() + +def getPlayer(): + return _player diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound_generator.py new file mode 100644 index 0000000..5c57af0 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/sound_generator.py @@ -0,0 +1,379 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for obtaining sounds to be presented for objects.""" + +__id__ = "$Id:$" +__version__ = "$Revision:$" +__date__ = "$Date:$" +__copyright__ = "Copyright (c) 2016 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version('Atspi', '2.0') +from gi.repository import Atspi + +import os + +from . import generator +from . import settings_manager +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +METHOD_PREFIX = "_generate" + + +class Icon: + """Sound file representing a particular aspect of an object.""" + + def __init__(self, location, filename): + self.path = os.path.join(location, filename) + + def __str__(self): + return f'Icon(path: {self.path}, isValid: {self.isValid()})' + + def isValid(self): + return os.path.isfile(self.path) + +class Tone: + """Tone representing a particular aspect of an object.""" + + SINE_WAVE = 0 + SQUARE_WAVE = 1 + SAW_WAVE = 2 + TRIANGLE_WAVE = 3 + SILENCE = 4 + WHITE_UNIFORM_NOISE = 5 + PINK_NOISE = 6 + SINE_WAVE_USING_TABLE = 7 + PERIODIC_TICKS = 8 + WHITE_GAUSSIAN_NOISE = 9 + RED_NOISE = 10 + INVERTED_PINK_NOISE = 11 + INVERTED_RED_NOISE = 12 + + def __init__(self, duration, frequency, volumeMultiplier=1, wave=SINE_WAVE): + self.duration = duration + self.frequency = min(max(0, frequency), 20000) + self.volume = _settingsManager.getSetting('soundVolume') * volumeMultiplier + self.wave = wave + + def __str__(self): + return 'Tone(duration: %s, frequency: %s, volume: %s, wave: %s)' \ + % (self.duration, self.frequency, self.volume, self.wave) + +class SoundGenerator(generator.Generator): + """Takes accessible objects and produces the sound(s) to be played.""" + + def __init__(self, script): + super().__init__(script, 'sound') + self._sounds = os.path.join(_settingsManager.getPrefsDir(), 'sounds') + + def _convertFilenameToIcon(self, filename): + icon = Icon(self._sounds, filename) + if icon.isValid(): + return icon + + return None + + def generateSound(self, obj, **args): + """Returns an array of sounds for the complete presentation of obj.""" + + return self.generate(obj, **args) + + ##################################################################### + # # + # State information # + # # + ##################################################################### + + def _generateAvailability(self, obj, **args): + """Returns an array of sounds indicating obj is grayed out.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateAvailability(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateCheckedState(self, obj, **args): + """Returns an array of sounds indicating the checked state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateCheckedState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateClickable(self, obj, **args): + """Returns an array of sounds indicating obj is clickable.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateClickable(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateExpandableState(self, obj, **args): + """Returns an array of sounds indicating the expanded state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateExpandableState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateHasLongDesc(self, obj, **args): + """Returns an array of sounds indicating obj has a longdesc.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateHasLongDesc(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateMenuItemCheckedState(self, obj, **args): + """Returns an array of sounds indicating the checked state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateMenuItemCheckedState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateMultiselectableState(self, obj, **args): + """Returns an array of sounds indicating obj is multiselectable.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateMultiselectableState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateRadioState(self, obj, **args): + """Returns an array of sounds indicating the selected state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateRadioState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateReadOnly(self, obj, **args): + """Returns an array of sounds indicating obj is read only.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateReadOnly(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateRequired(self, obj, **args): + """Returns an array of sounds indicating obj is required.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateRequired(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateSwitchState(self, obj, **args): + """Returns an array of sounds indicating the on/off state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateSwitchState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateToggleState(self, obj, **args): + """Returns an array of sounds indicating the toggled state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + filenames = super()._generateToggleState(obj, **args) + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + def _generateVisitedState(self, obj, **args): + """Returns an array of sounds indicating the visited state of obj.""" + + if not _settingsManager.getSetting('playSoundForState'): + return [] + + if not args.get('mode', None): + args['mode'] = self._mode + + args['stringType'] = 'visited' + if AXUtilities.is_visited(obj): + filenames = [self._script.formatting.getString(**args)] + result = list(map(self._convertFilenameToIcon, filenames)) + if result: + return result + + return [] + + ##################################################################### + # # + # Value interface information # + # # + ##################################################################### + + def _generatePercentage(self, obj, **args): + """Returns an array of sounds reflecting the percentage of obj.""" + + if not _settingsManager.getSetting('playSoundForValue'): + return [] + + percent = self._script.utilities.getValueAsPercent(obj) + if percent is None: + return [] + + return [] + + def _generateProgressBarValue(self, obj, **args): + """Returns an array of sounds representing the progress bar value.""" + + if args.get('isProgressBarUpdate'): + if not self._shouldPresentProgressBarUpdate(obj, **args): + return [] + elif not _settingsManager.getSetting('playSoundForValue'): + return [] + + percent = self._script.utilities.getValueAsPercent(obj) + if percent is None: + return [] + + # To better indicate the progress completion. + if percent >= 99: + duration = 1 + else: + duration = 0.075 + + # Reduce volume as pitch increases. + volumeMultiplier = 1 - (percent / 120) + + # Adjusting so that the initial beeps are not too deep. + if percent < 7: + frequency = int(98 + percent * 5.4) + else: + frequency = int(percent * 22) + + return [Tone(duration, frequency, volumeMultiplier, Tone.SINE_WAVE)] + + def _getProgressBarUpdateInterval(self): + interval = _settingsManager.getSetting('progressBarBeepInterval') + if interval is None: + return super()._getProgressBarUpdateInterval() + + return int(interval) + + def _shouldPresentProgressBarUpdate(self, obj, **args): + if not _settingsManager.getSetting('beepProgressBarUpdates'): + return False + + return super()._shouldPresentProgressBarUpdate(obj, **args) + + ##################################################################### + # # + # Role and hierarchical information # + # # + ##################################################################### + + def _generatePositionInSet(self, obj, **args): + """Returns an array of sounds reflecting the set position of obj.""" + + if not _settingsManager.getSetting('playSoundForPositionInSet'): + return [] + + # TODO: Implement the result. + # position, setSize = self._script.utilities.getPositionAndSetSize(obj) + # percent = int((position / setSize) * 100) + + return [] + + def _generateRoleName(self, obj, **args): + """Returns an array of sounds indicating the role of obj.""" + + if not _settingsManager.getSetting('playSoundForRole'): + return [] + + role = args.get('role', AXObject.get_role(obj)) + filename = Atspi.role_get_name(role).replace(' ', '_') + result = self._convertFilenameToIcon(filename) + if result: + return [result] + + return [] diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech.py new file mode 100644 index 0000000..31ddc6d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech.py @@ -0,0 +1,324 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Manages the default speech server for cthulhu. A script can use this +as its speech server, or it can feel free to create one of its own.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import importlib +import time + +from . import debug +from . import logger +from . import settings +from . import speech_generator +from .speechserver import VoiceFamily + +from .acss import ACSS + +_logger = logger.getLogger() +log = _logger.newLog("speech") + +# The speech server to use for all speech operations. +# +_speechserver = None + +# The last time something was spoken. +_timestamp = 0 + +def _initSpeechServer(moduleName, speechServerInfo): + + global _speechserver + + if not moduleName: + return + + factory = None + try: + factory = importlib.import_module(f'cthulhu.{moduleName}') + except Exception: + try: + factory = importlib.import_module(moduleName) + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + # Now, get the speech server we care about. + # + speechServerInfo = settings.speechServerInfo + if speechServerInfo: + _speechserver = factory.SpeechServer.getSpeechServer(speechServerInfo) + + if not _speechserver: + _speechserver = factory.SpeechServer.getSpeechServer() + if speechServerInfo: + tokens = ["SPEECH: Invalid speechServerInfo:", speechServerInfo] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if not _speechserver: + raise Exception(f"ERROR: No speech server for factory: {moduleName}") + +def init(): + debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Initializing', True) + if _speechserver: + debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Already initialized', True) + return + + try: + moduleName = settings.speechServerFactory + _initSpeechServer(moduleName, settings.speechServerInfo) + except Exception: + moduleNames = settings.speechFactoryModules + for moduleName in moduleNames: + if moduleName != settings.speechServerFactory: + try: + _initSpeechServer(moduleName, None) + if _speechserver: + break + except Exception: + debug.printException(debug.LEVEL_SEVERE) + + if _speechserver: + tokens = ["SPEECH: Using speech server factory:", moduleName] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + else: + msg = 'SPEECH: Not available' + debug.printMessage(debug.LEVEL_INFO, msg, True) + + debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Initialized', True) + +def checkSpeechSetting(): + msg = "SPEECH: Checking speech setting." + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if not settings.enableSpeech: + shutdown() + else: + init() + +def __resolveACSS(acss=None): + if isinstance(acss, ACSS): + family = acss.get(acss.FAMILY) + try: + family = VoiceFamily(family) + except Exception: + family = VoiceFamily({}) + acss[acss.FAMILY] = family + return acss + elif isinstance(acss, list) and len(acss) == 1: + return ACSS(acss[0]) + elif isinstance(acss, dict): + return ACSS(acss) + else: + voices = settings.voices + return ACSS(voices[settings.DEFAULT_VOICE]) + +def sayAll(utteranceIterator, progressCallback): + if settings.silenceSpeech: + return + if _speechserver: + _speechserver.sayAll(utteranceIterator, progressCallback) + else: + for [context, acss] in utteranceIterator: + logLine = f"SPEECH OUTPUT: '{context.utterance}'" + debug.printMessage(debug.LEVEL_INFO, logLine, True) + log.info(logLine) + +def _speak(text, acss, interrupt): + """Speaks the individual string using the given ACSS.""" + + if not _speechserver: + logLine = f"SPEECH OUTPUT: '{text}' {acss}" + debug.printMessage(debug.LEVEL_INFO, logLine, True) + log.info(logLine) + return + + voice = ACSS(settings.voices.get(settings.DEFAULT_VOICE)) + try: + voice.update(__resolveACSS(acss)) + except Exception as error: + msg = f"SPEECH: Exception updated voice with {acss}: {error}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + + resolvedVoice = __resolveACSS(voice) + msg = f"SPEECH OUTPUT: '{text}' {resolvedVoice}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + _speechserver.speak(text, resolvedVoice, interrupt) + +def speak(content, acss=None, interrupt=True): + """Speaks the given content. The content can be either a simple + string or an array of arrays of objects returned by a speech + generator.""" + + if settings.silenceSpeech: + return + + validTypes = (str, list, speech_generator.Pause, + speech_generator.LineBreak, ACSS) + error = "SPEECH: bad content sent to speak(): '%s'" + if not isinstance(content, validTypes): + debug.printMessage(debug.LEVEL_INFO, error % content, True) + return + + global _timestamp + if _timestamp: + msg = f"SPEECH: Last spoke {time.time() - _timestamp:.4f} seconds ago" + debug.printMessage(debug.LEVEL_INFO, msg, True) + _timestamp = time.time() + + if isinstance(content, str): + msg = f"SPEECH: Speak '{content}' acss: {acss}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + tokens = ["SPEECH: Speak", content, ", acss:", acss] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + if isinstance(content, str): + _speak(content, acss, interrupt) + if not isinstance(content, list): + return + + toSpeak = [] + activeVoice = acss + if acss is not None: + activeVoice = ACSS(acss) + + for element in content: + if not isinstance(element, validTypes): + debug.printMessage(debug.LEVEL_INFO, error % element, True) + elif isinstance(element, list): + speak(element, acss, interrupt) + elif isinstance(element, str): + if len(element): + toSpeak.append(element) + elif toSpeak: + newVoice = ACSS(acss) + newItemsToSpeak = [] + if isinstance(element, speech_generator.Pause): + if toSpeak[-1] and toSpeak[-1][-1].isalnum(): + toSpeak[-1] += '.' + elif isinstance(element, ACSS): + newVoice.update(element) + if activeVoice is None: + activeVoice = newVoice + if newVoice == activeVoice: + continue + tokens = ["SPEECH: New voice", newVoice, " != active voice", activeVoice] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + newItemsToSpeak.append(toSpeak.pop()) + + if toSpeak: + string = " ".join(toSpeak) + _speak(string, activeVoice, interrupt) + activeVoice = newVoice + toSpeak = newItemsToSpeak + + if toSpeak: + string = " ".join(toSpeak) + _speak(string, activeVoice, interrupt) + +def speakKeyEvent(event, acss=None): + """Speaks a key event immediately. + + Arguments: + - event: input_event.KeyboardEvent to speak. + """ + + if settings.silenceSpeech: + return + + global _timestamp + if _timestamp: + msg = f"SPEECH: Last spoke {time.time() - _timestamp:.4f} seconds ago" + debug.printMessage(debug.LEVEL_INFO, msg, True) + _timestamp = time.time() + + keyname = event.getKeyName() + lockingStateString = event.getLockingStateString() + acss = __resolveACSS(acss) + msg = f"{keyname} {lockingStateString}" + logLine = f"SPEECH OUTPUT: '{msg.strip()}' {acss}" + debug.printMessage(debug.LEVEL_INFO, logLine, True) + log.info(logLine) + + if _speechserver: + _speechserver.speakKeyEvent(event, acss) + +def speakCharacter(character, acss=None): + """Speaks a single character immediately. + + Arguments: + - character: text to be spoken + - acss: acss.ACSS instance; if None, + the default voice settings will be used. + Otherwise, the acss settings will be + used to augment/override the default + voice settings. + """ + if settings.silenceSpeech: + return + + global _timestamp + if _timestamp: + msg = f"SPEECH: Last spoke {time.time() - _timestamp:.4f} seconds ago" + debug.printMessage(debug.LEVEL_INFO, msg, True) + _timestamp = time.time() + + acss = __resolveACSS(acss) + tokens = [f"SPEECH OUTPUT: '{character}'", acss] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + log.info(f"SPEECH OUTPUT: '{character}'") + + if _speechserver: + _speechserver.speakCharacter(character, acss=acss) + +def getInfo(): + info = None + if _speechserver: + info = _speechserver.getInfo() + + return info + +def stop(): + if _speechserver: + _speechserver.stop() + +def shutdown(): + debug.printMessage(debug.LEVEL_INFO, 'SPEECH: Shutting down', True) + global _speechserver + if _speechserver: + _speechserver.shutdownActiveServers() + _speechserver = None + +def reset(text=None, acss=None): + if _speechserver: + _speechserver.reset(text, acss) + +def getSpeechServer(): + return _speechserver diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_and_verbosity_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_and_verbosity_manager.py new file mode 100644 index 0000000..6a5cc99 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_and_verbosity_manager.py @@ -0,0 +1,562 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for configuring speech and verbosity settings.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2016-2023 Igalia, S.L." +__license__ = "LGPL" + +from . import cmdnames +from . import debug +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu_state +from . import settings +from . import settings_manager +from . import speech + +_settings_manager = settings_manager.getManager() + +class SpeechAndVerbosityManager: + """Configures speech and verbosity settings.""" + + def __init__(self): + self._handlers = self._setup_handlers() + self._bindings = self._setup_bindings() + + def get_bindings(self): + """Returns the notification-presenter keybindings.""" + + return self._bindings + + def get_handlers(self): + """Returns the notification-presenter handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the speech and verbosity input event handlers.""" + + handlers = {} + + handlers["cycleCapitalizationStyleHandler"] = \ + input_event.InputEventHandler( + self.cycle_capitalization_style, + cmdnames.CYCLE_CAPITALIZATION_STYLE) + + handlers["cycleSpeakingPunctuationLevelHandler"] = \ + input_event.InputEventHandler( + self.cycle_punctuation_level, + cmdnames.CYCLE_PUNCTUATION_LEVEL) + + handlers["cycleSynthesizerHandler"] = \ + input_event.InputEventHandler( + self.cycle_synthesizer, + cmdnames.CYCLE_SYNTHESIZER) + + handlers["cycleKeyEchoHandler"] = \ + input_event.InputEventHandler( + self.cycle_key_echo, + cmdnames.CYCLE_KEY_ECHO) + + handlers["changeNumberStyleHandler"] = \ + input_event.InputEventHandler( + self.change_number_style, + cmdnames.CHANGE_NUMBER_STYLE) + + handlers["toggleSilenceSpeechHandler"] = \ + input_event.InputEventHandler( + self.toggle_speech, + cmdnames.TOGGLE_SPEECH) + + handlers["toggleSpeechVerbosityHandler"] = \ + input_event.InputEventHandler( + self.toggle_verbosity, + cmdnames.TOGGLE_SPEECH_VERBOSITY) + + handlers["toggleSpeakingIndentationJustificationHandler"] = \ + input_event.InputEventHandler( + self.toggle_indentation_and_justification, + cmdnames.TOGGLE_SPOKEN_INDENTATION_AND_JUSTIFICATION) + + handlers["toggleTableCellReadModeHandler"] = \ + input_event.InputEventHandler( + self.toggle_table_cell_reading_mode, + cmdnames.TOGGLE_TABLE_CELL_READ_MODE) + + handlers["decreaseSpeechRateHandler"] = \ + input_event.InputEventHandler( + self.decrease_rate, + cmdnames.DECREASE_SPEECH_RATE) + + handlers["increaseSpeechRateHandler"] = \ + input_event.InputEventHandler( + self.increase_rate, + cmdnames.INCREASE_SPEECH_RATE) + + handlers["decreaseSpeechPitchHandler"] = \ + input_event.InputEventHandler( + self.decrease_pitch, + cmdnames.DECREASE_SPEECH_PITCH) + + handlers["increaseSpeechPitchHandler"] = \ + input_event.InputEventHandler( + self.increase_pitch, + cmdnames.INCREASE_SPEECH_PITCH) + + handlers["decreaseSpeechVolumeHandler"] = \ + input_event.InputEventHandler( + self.decrease_volume, + cmdnames.DECREASE_SPEECH_VOLUME) + + handlers["increaseSpeechVolumeHandler"] = \ + input_event.InputEventHandler( + self.increase_volume, + cmdnames.INCREASE_SPEECH_VOLUME) + + return handlers + + def _setup_bindings(self): + """Sets up and returns the speech and verbosity key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("cycleCapitalizationStyleHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("cycleSpeakingPunctuationLevelHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("cycleSynthesizerHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("cycleKeyEchoHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("changeNumberStyleHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("decreaseSpeechRateHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("increaseSpeechRateHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("decreaseSpeechPitchHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("increaseSpeechPitchHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("decreaseSpeechVolumeHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("increaseSpeechVolumeHandler"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("toggleSpeakingIndentationJustificationHandler"))) + + bindings.add( + keybindings.KeyBinding( + "s", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("toggleSilenceSpeechHandler"))) + + bindings.add( + keybindings.KeyBinding( + "v", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("toggleSpeechVerbosityHandler"))) + + bindings.add( + keybindings.KeyBinding( + "F11", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("toggleTableCellReadModeHandler"))) + + return bindings + + def _get_server(self): + return speech.getSpeechServer() + + def decrease_rate(self, script, event=None): + """Decreases the speech rate""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.decreaseSpeechRate() + return True + + def increase_rate(self, script, event=None): + """Increases the speech rate""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.increaseSpeechRate() + return True + + def decrease_pitch(self, script, event=None): + """Decreases the speech pitch""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.decreaseSpeechPitch() + return True + + def increase_pitch(self, script, event=None): + """Increase the speech pitch""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.increaseSpeechPitch() + return True + + def decrease_volume(self, script, event=None): + """Decreases the speech volume""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.decreaseSpeechVolume() + return True + + def increase_volume(self, script, event=None): + """Increases the speech volume""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.increaseSpeechVolume() + return True + + def update_capitalization_style(self): + """Updates the capitalization style based on the value in settings.""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.updateCapitalizationStyle() + return True + + def update_punctuation_level(self): + """Updates the punctuation level based on the value in settings.""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + server.updatePunctuationLevel() + return True + + def cycle_synthesizer(self, script, event=None): + """Cycle through the speech-dispatcher's available output modules.""" + + server = self._get_server() + if server is None: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get speech server." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + available = server.list_output_modules() + if not available: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get output modules." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + current = server.getOutputModule() + if not current: + msg = "SPEECH AND VERBOSITY MANAGER: Cannot get current output module." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + index = available.index(current) + 1 + if index == len(available): + index = 0 + + server.setOutputModule(available[index]) + script.presentMessage(available[index]) + return True + + def cycle_capitalization_style(self, script, event=None): + """Cycle through the speech-dispatcher capitalization styles.""" + + current_style = _settings_manager.getSetting('capitalizationStyle') + if current_style == settings.CAPITALIZATION_STYLE_NONE: + new_style = settings.CAPITALIZATION_STYLE_SPELL + full = messages.CAPITALIZATION_SPELL_FULL + brief = messages.CAPITALIZATION_SPELL_BRIEF + elif current_style == settings.CAPITALIZATION_STYLE_SPELL: + new_style = settings.CAPITALIZATION_STYLE_ICON + full = messages.CAPITALIZATION_ICON_FULL + brief = messages.CAPITALIZATION_ICON_BRIEF + else: + new_style = settings.CAPITALIZATION_STYLE_NONE + full = messages.CAPITALIZATION_NONE_FULL + brief = messages.CAPITALIZATION_NONE_BRIEF + + _settings_manager.setSetting('capitalizationStyle', new_style) + script.presentMessage(full, brief) + self.update_capitalization_style() + return True + + def cycle_punctuation_level(self, script, event=None): + """Cycle through the punctuation levels for speech.""" + + current_level = _settings_manager.getSetting('verbalizePunctuationStyle') + if current_level == settings.PUNCTUATION_STYLE_NONE: + new_level = settings.PUNCTUATION_STYLE_SOME + full = messages.PUNCTUATION_SOME_FULL + brief = messages.PUNCTUATION_SOME_BRIEF + elif current_level == settings.PUNCTUATION_STYLE_SOME: + new_level = settings.PUNCTUATION_STYLE_MOST + full = messages.PUNCTUATION_MOST_FULL + brief = messages.PUNCTUATION_MOST_BRIEF + elif current_level == settings.PUNCTUATION_STYLE_MOST: + new_level = settings.PUNCTUATION_STYLE_ALL + full = messages.PUNCTUATION_ALL_FULL + brief = messages.PUNCTUATION_ALL_BRIEF + else: + new_level = settings.PUNCTUATION_STYLE_NONE + full = messages.PUNCTUATION_NONE_FULL + brief = messages.PUNCTUATION_NONE_BRIEF + + _settings_manager.setSetting('verbalizePunctuationStyle', new_level) + script.presentMessage(full, brief) + self.update_punctuation_level() + return True + + def cycle_key_echo(self, script, event=None): + """Cycle through the key echo levels.""" + (new_key, new_word, new_sentence) = (False, False, False) + key = _settings_manager.getSetting('enableKeyEcho') + word = _settings_manager.getSetting('enableEchoByWord') + sentence = _settings_manager.getSetting('enableEchoBySentence') + + if (key, word, sentence) == (False, False, False): + (new_key, new_word, new_sentence) = (True, False, False) + full = messages.KEY_ECHO_KEY_FULL + brief = messages.KEY_ECHO_KEY_BRIEF + elif (key, word, sentence) == (True, False, False): + (new_key, new_word, new_sentence) = (False, True, False) + full = messages.KEY_ECHO_WORD_FULL + brief = messages.KEY_ECHO_WORD_BRIEF + elif (key, word, sentence) == (False, True, False): + (new_key, new_word, new_sentence) = (False, False, True) + full = messages.KEY_ECHO_SENTENCE_FULL + brief = messages.KEY_ECHO_SENTENCE_BRIEF + elif (key, word, sentence) == (False, False, True): + (new_key, new_word, new_sentence) = (True, True, False) + full = messages.KEY_ECHO_KEY_AND_WORD_FULL + brief = messages.KEY_ECHO_KEY_AND_WORD_BRIEF + elif (key, word, sentence) == (True, True, False): + (new_key, new_word, new_sentence) = (False, True, True) + full = messages.KEY_ECHO_WORD_AND_SENTENCE_FULL + brief = messages.KEY_ECHO_WORD_AND_SENTENCE_BRIEF + else: + (new_key, new_word, new_sentence) = (False, False, False) + full = messages.KEY_ECHO_NONE_FULL + brief = messages.KEY_ECHO_NONE_BRIEF + + _settings_manager.setSetting('enableKeyEcho', new_key) + _settings_manager.setSetting('enableEchoByWord', new_word) + _settings_manager.setSetting('enableEchoBySentence', new_sentence) + script.presentMessage(full, brief) + return True + + def change_number_style(self, script, event=None): + """Changes spoken number style between digits and words.""" + + speak_digits = _settings_manager.getSetting('speakNumbersAsDigits') + if speak_digits: + brief = messages.NUMBER_STYLE_WORDS_BRIEF + full = messages.NUMBER_STYLE_WORDS_FULL + else: + brief = messages.NUMBER_STYLE_DIGITS_BRIEF + full = messages.NUMBER_STYLE_DIGITS_FULL + + _settings_manager.setSetting('speakNumbersAsDigits', not speak_digits) + script.presentMessage(full, brief) + return True + + def toggle_speech(self, script, event=None): + """Toggles speech.""" + + script.presentationInterrupt() + if _settings_manager.getSetting('silenceSpeech'): + _settings_manager.setSetting('silenceSpeech', False) + script.presentMessage(messages.SPEECH_ENABLED) + elif not _settings_manager.getSetting('enableSpeech'): + _settings_manager.setSetting('enableSpeech', True) + speech.init() + script.presentMessage(messages.SPEECH_ENABLED) + else: + script.presentMessage(messages.SPEECH_DISABLED) + _settings_manager.setSetting('silenceSpeech', True) + return True + + def toggle_verbosity(self, script, event=None): + """Toggles speech verbosity level between verbose and brief.""" + + value = _settings_manager.getSetting('speechVerbosityLevel') + if value == settings.VERBOSITY_LEVEL_BRIEF: + script.presentMessage(messages.SPEECH_VERBOSITY_VERBOSE) + _settings_manager.setSetting('speechVerbosityLevel', settings.VERBOSITY_LEVEL_VERBOSE) + else: + script.presentMessage(messages.SPEECH_VERBOSITY_BRIEF) + _settings_manager.setSetting('speechVerbosityLevel', settings.VERBOSITY_LEVEL_BRIEF) + return True + + def toggle_indentation_and_justification(self, script, event=None): + """Toggles the speaking of indentation and justification.""" + + value = _settings_manager.getSetting('enableSpeechIndentation') + _settings_manager.setSetting('enableSpeechIndentation', not value) + if _settings_manager.getSetting('enableSpeechIndentation'): + full = messages.INDENTATION_JUSTIFICATION_ON_FULL + brief = messages.INDENTATION_JUSTIFICATION_ON_BRIEF + else: + full = messages.INDENTATION_JUSTIFICATION_OFF_FULL + brief = messages.INDENTATION_JUSTIFICATION_OFF_BRIEF + script.presentMessage(full, brief) + return True + + def toggle_table_cell_reading_mode(self, script, event=None): + """Toggles between speak cell and speak row.""" + + table = script.utilities.getTable(cthulhu_state.locusOfFocus) + if not table: + script.presentMessage(messages.TABLE_NOT_IN_A) + return True + + if not script.utilities.getDocumentForObject(table): + setting_name = 'readFullRowInGUITable' + elif script.utilities.isSpreadSheetTable(table): + setting_name = 'readFullRowInSpreadSheet' + else: + setting_name = 'readFullRowInDocumentTable' + + speak_row = _settings_manager.getSetting(setting_name) + _settings_manager.setSetting(setting_name, not speak_row) + + if not speak_row: + msg = messages.TABLE_MODE_ROW + else: + msg = messages.TABLE_MODE_CELL + + script.presentMessage(msg) + return True + +_manager = None +def getManager(): + """Returns the Speech and Verbosity Manager""" + + global _manager + if _manager is None: + _manager = SpeechAndVerbosityManager() + return _manager diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_generator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_generator.py new file mode 100644 index 0000000..b77143d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speech_generator.py @@ -0,0 +1,2953 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for obtaining speech utterances for objects.""" + +__id__ = "$Id:$" +__version__ = "$Revision:$" +__date__ = "$Date:$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import functools +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import urllib.parse +import urllib.request +import urllib.error +import urllib.parse + +from . import acss +from . import chnames +from . import debug +from . import generator +from . import messages +from . import object_properties +from . import settings +from . import settings_manager +from . import speech +from . import text_attribute_names +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +class Pause: + """A dummy class to indicate we want to insert a pause into an + utterance.""" + def __init__(self): + pass + + def __str__(self): + return "PAUSE" + +PAUSE = [Pause()] + +class LineBreak: + """A dummy class to indicate we want to break an utterance into + separate calls to speak.""" + def __init__(self): + pass + + def __str__(self): + return "LINE BREAK" + +LINE_BREAK = [LineBreak()] + +# [[[WDW - general note -- for all the _generate* methods, it would be great if +# we could return an empty array if we can determine the method does not +# apply to the object. This would allow us to reduce the number of strings +# needed in formatting.py.]]] + +# The prefix to use for the individual generator methods +# +METHOD_PREFIX = "_generate" + +DEFAULT = "default" +UPPERCASE = "uppercase" +HYPERLINK = "hyperlink" +SYSTEM = "system" +STATE = "state" # Candidate for sound +VALUE = "value" # Candidate for sound + +voiceType = { + DEFAULT: settings.DEFAULT_VOICE, + UPPERCASE: settings.UPPERCASE_VOICE, + HYPERLINK: settings.HYPERLINK_VOICE, + SYSTEM: settings.SYSTEM_VOICE, + STATE: settings.SYSTEM_VOICE, # Users may prefer DEFAULT_VOICE here + VALUE: settings.SYSTEM_VOICE, # Users may prefer DEFAULT_VOICE here +} + +_settingsManager = settings_manager.getManager() + +class SpeechGenerator(generator.Generator): + """Takes accessible objects and produces a string to speak for + those objects. See the generateSpeech method, which is the primary + entry point. Subclasses can feel free to override/extend the + speechGenerators instance field as they see fit.""" + + def __init__(self, script): + generator.Generator.__init__(self, script, "speech") + + def _addGlobals(self, globalsDict): + """Other things to make available from the formatting string. + """ + generator.Generator._addGlobals(self, globalsDict) + globalsDict['voice'] = self.voice + + def generateSpeech(self, obj, **args): + rv = self.generate(obj, **args) + if rv and not list(filter(lambda x: not isinstance(x, Pause), rv)): + tokens = ["SPEECH GENERATOR: Results for", obj, "are pauses only"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + rv = [] + + return rv + + def _resultElementToString(self, element, includeAll=True): + if isinstance(element, acss.ACSS) and not includeAll: + return "" + + if isinstance(element, list): + rv = [self._resultElementToString(x, includeAll) for x in element] + return " ".join(filter(lambda x: x, rv)) + + return super()._resultElementToString(element, includeAll) + + ##################################################################### + # # + # Name, role, and label information # + # # + ##################################################################### + + def _generateName(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the name of the object. If the object is directly + displaying any text, that text will be treated as the name. + Otherwise, the accessible name of the object will be used. If + there is no accessible name, then the description of the + object will be used. This method will return an empty array + if nothing can be found. [[[WDW - I wonder if we should just + have _generateName, _generateDescription, + _generateDisplayedText, etc., that don't do any fallback. + Then, we can allow the formatting to do the fallback (e.g., + 'displayedText or name or description'). [[[JD to WDW - I + needed a _generateDescription for whereAmI. :-) See below. + """ + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.LAYERED_PANE \ + and _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateName(self, obj, **args) + if result: + if role == Atspi.Role.LAYERED_PANE: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + else: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + + return result + + def _generateLabel(self, obj, **args): + """Returns the label for an object as an array of strings for use by + speech and braille. The label is determined by the displayedLabel + method of the script utility, and an empty array will be returned if + no label can be found. + """ + + result = generator.Generator._generateLabel(self, obj, **args) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + def _generateLabelOrName(self, obj, **args): + """Returns the label as an array of strings for speech and braille. + If the label cannot be found, the name will be used instead. + If the name cannot be found, an empty array will be returned. + """ + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.MENU and self._script.utilities.isPopupMenuForCurrentItem(obj): + tokens = ["SPEECH GENERATOR:", obj, "is popup menu for current item."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + result = [] + result.extend(self._generateLabel(obj, **args)) + if not result: + name = AXObject.get_name(obj) + if name: + result.append(name) + result.extend(self.voice(DEFAULT, obj=obj, **args)) + if result: + return result + + parent = AXObject.get_parent(obj) + if AXUtilities.is_autocomplete(parent): + result = self._generateLabelOrName(parent, **args) + + return result + + def _generatePlaceholderText(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the 'placeholder' text. This is typically text that + serves as a functional label and is found in a text widget until + that widget is given focus at which point the text is removed, + the assumption being that the user was able to see the text prior + to giving the widget focus. + """ + + result = generator.Generator._generatePlaceholderText(self, obj, **args) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + def _generateAlertText(self, obj, **args): + result = self._generateExpandedEOCs(obj, **args) \ + or self._generateUnrelatedLabels(obj, **args) + if result: + self._script.pointOfReference['usedDescriptionForAlert'] = False + return result + + args['alerttext'] = True + result = self._generateDescription(obj, **args) + if result: + self._script.pointOfReference['usedDescriptionForAlert'] = True + + return result + + def _generateDescription(self, obj, **args): + """Returns an array of strings fo use by speech and braille that + represent the description of the object, if that description + is different from that of the name and label. + """ + + alreadyUsed = False + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.ALERT: + try: + alreadyUsed = self._script.pointOfReference.pop('usedDescriptionForAlert') + except Exception: + pass + else: + try: + alreadyUsed = self._script.pointOfReference.pop('usedDescriptionForUnrelatedLabels') + except Exception: + pass + + if alreadyUsed: + return [] + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not _settingsManager.getSetting('speakDescription') and not args.get('alerttext'): + return [] + + if args.get('inMouseReview') and not _settingsManager.getSetting('presentToolTips'): + return [] + + priorObj = args.get('priorObj') + if AXUtilities.is_tool_tip(priorObj): + return [] + + if priorObj == obj: + return [] + + result = generator.Generator._generateDescription(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateImageDescription(self, obj, **args ): + """Returns an array of strings for use by speech and braille that + represent the description of the image on the object.""" + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if not _settingsManager.getSetting('speakDescription'): + return [] + + result = generator.Generator._generateImageDescription(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateReadOnly(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the read only state of this object, but only if it + is read only (i.e., it is a text area that cannot be edited). + """ + + result = generator.Generator._generateReadOnly(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateHasPopup(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or _settingsManager.getSetting('speechVerbosityLevel') \ + == settings.VERBOSITY_LEVEL_BRIEF: + return [] + + result = generator.Generator._generateHasPopup(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateClickable(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or _settingsManager.getSetting('speechVerbosityLevel') \ + == settings.VERBOSITY_LEVEL_BRIEF: + return [] + + result = generator.Generator._generateClickable(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateHasLongDesc(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateHasLongDesc(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateHasDetails(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateHasDetails(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateDetailsFor(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateDetailsFor(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateAllDetails(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateAllDetails(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateDeletionStart(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + startOffset = args.get('startOffset', 0) + if startOffset != 0: + return [] + + result = [] + if self._script.utilities.isFirstItemInInlineContentSuggestion(obj): + result.extend([object_properties.ROLE_CONTENT_SUGGESTION]) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generatePause(obj, **args)) + + result.extend([messages.CONTENT_DELETION_START]) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateDeletionEnd(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + endOffset = args.get('endOffset') + if endOffset is not None: + text = self._script.utilities.queryNonEmptyText(obj) + if text and text.characterCount != endOffset: + return [] + + result = [messages.CONTENT_DELETION_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + if self._script.utilities.isLastItemInInlineContentSuggestion(obj): + result.extend(self._generatePause(obj, **args)) + result.extend([messages.CONTENT_SUGGESTION_END]) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + container = AXObject.find_ancestor(obj, self._script.utilities.hasDetails) + if self._script.utilities.isContentSuggestion(container): + result.extend(self._generatePause(obj, **args)) + result.extend(self._generateHasDetails(container, mode=args.get('mode'))) + + return result + + def _generateInsertionStart(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + startOffset = args.get('startOffset', 0) + if startOffset != 0: + return [] + + result = [] + if self._script.utilities.isFirstItemInInlineContentSuggestion(obj): + result.extend([object_properties.ROLE_CONTENT_SUGGESTION]) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generatePause(obj, **args)) + + result.extend([messages.CONTENT_INSERTION_START]) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateInsertionEnd(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + endOffset = args.get('endOffset') + if endOffset is not None: + text = self._script.utilities.queryNonEmptyText(obj) + if text and text.characterCount != endOffset: + return [] + + result = [messages.CONTENT_INSERTION_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + if self._script.utilities.isLastItemInInlineContentSuggestion(obj): + result.extend(self._generatePause(obj, **args)) + result.extend([messages.CONTENT_SUGGESTION_END]) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + container = AXObject.find_ancestor(obj, self._script.utilities.hasDetails) + if self._script.utilities.isContentSuggestion(container): + result.extend(self._generatePause(obj, **args)) + result.extend(self._generateHasDetails(container, mode=args.get('mode'))) + + return result + + def _generateMarkStart(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + startOffset = args.get('startOffset', 0) + if startOffset != 0: + return [] + + result = [] + roledescription = self._script.utilities.getRoleDescription(obj) + if roledescription: + result.append(roledescription) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generatePause(obj, **args)) + + result.append(messages.CONTENT_MARK_START) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateMarkEnd(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + endOffset = args.get('endOffset') + if endOffset is not None: + text = self._script.utilities.queryNonEmptyText(obj) + if text and text.characterCount != endOffset: + return [] + + result = [messages.CONTENT_MARK_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateAvailability(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateAvailability(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateInvalid(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateInvalid(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateRequired(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateRequired(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateTable(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if args.get("leaving"): + return[] + + if self._script.utilities.isTextDocumentTable(obj): + role = args.get('role', AXObject.get_role(obj)) + enabled, disabled = self._getEnabledAndDisabledContextRoles() + if role in disabled: + return [] + + if _settingsManager.getSetting('speechVerbosityLevel') == settings.VERBOSITY_LEVEL_BRIEF: + return self._generateRoleName(obj, **args) + + result = generator.Generator._generateTable(self, obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateTextRole(self, obj, **args): + """A convenience method to prevent the Atspi.Role.PARAGRAPH role + from being spoken. In the case of a Atspi.Role.PARAGRAPH + role, an empty array will be returned. In all other cases, the + role name will be returned as an array of strings (and + possibly voice and audio specifications). Note that a 'role' + attribute in args will override the accessible role of the + obj. [[[WDW - I wonder if this should be moved to + _generateRoleName. Or, maybe make a 'do not speak roles' attribute + of a speech generator that we can update and the user can + override.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role != Atspi.Role.PARAGRAPH: + result.extend(self._generateRoleName(obj, **args)) + return result + + def _generateRoleName(self, obj, **args): + """Returns the role name for the object in an array of strings (and + possibly voice and audio specifications), with the exception + that the Atspi.Role.UNKNOWN role will yield an empty array. + Note that a 'role' attribute in args will override the + accessible role of the obj. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if self._script.utilities.isStatusBarNotification(obj): + return [] + + if self._script.utilities.isDesktop(obj): + return [] + + if self._script.utilities.isDockedFrame(obj): + return [] + + result = [] + role = args.get('role', AXObject.get_role(obj)) + + doNotPresent = [Atspi.Role.UNKNOWN, + Atspi.Role.REDUNDANT_OBJECT, + Atspi.Role.FILLER, + Atspi.Role.EXTENDED] + + parent = AXObject.get_parent(obj) + if role == Atspi.Role.MENU and AXUtilities.is_combo_box(parent): + return self._generateRoleName(parent) + + if self._script.utilities.isSingleLineAutocompleteEntry(obj): + result.append(self.getLocalizedRoleName(obj, role=Atspi.Role.AUTOCOMPLETE)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + if role == Atspi.Role.PANEL \ + and AXUtilities.is_selected(obj): + return [] + + # egg-list-box, e.g. privacy panel in gnome-control-center + if AXUtilities.is_list_box(parent): + doNotPresent.append(AXObject.get_role(obj)) + + if self._script.utilities.isStatusBarDescendant(obj): + doNotPresent.append(Atspi.Role.LABEL) + + if _settingsManager.getSetting('speechVerbosityLevel') \ + == settings.VERBOSITY_LEVEL_BRIEF: + doNotPresent.extend([Atspi.Role.ICON, Atspi.Role.CANVAS]) + + if role == Atspi.Role.HEADING: + level = self._script.utilities.headingLevel(obj) + if level: + result.append(object_properties.ROLE_HEADING_LEVEL_SPEECH % { + 'role': self.getLocalizedRoleName(obj, **args), + 'level': level}) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + if role not in doNotPresent and not result: + result.append(self.getLocalizedRoleName(obj, **args)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def getRoleName(self, obj, **args): + """Returns the role name for the object in an array of strings (and + possibly voice and audio specifications), with the exception + that the Atspi.Role.UNKNOWN role will yield an empty array. + Note that a 'role' attribute in args will override the + accessible role of the obj. This is provided mostly as a + method for scripts to call. + """ + generated = self._generateRoleName(obj, **args) + if generated: + return generated[0] + + return "" + + def getName(self, obj, **args): + generated = self._generateName(obj, **args) + if generated: + return generated[0] + + return "" + + def getLocalizedRoleName(self, obj, **args): + """Returns the localized name of the given Accessible object; the name + is suitable to be spoken. + + Arguments: + - obj: an Accessible object + """ + + if self._script.utilities.isEditableComboBox(obj) \ + or self._script.utilities.isEditableDescendantOfComboBox(obj): + return object_properties.ROLE_EDITABLE_COMBO_BOX + + role = args.get('role', AXObject.get_role(obj)) + if role == Atspi.Role.LINK and AXUtilities.is_visited(obj): + return object_properties.ROLE_VISITED_LINK + + return super().getLocalizedRoleName(obj, **args) + + def _generateUnrelatedLabels(self, obj, **args): + """Returns, as an array of strings (and possibly voice + specifications), all the labels which are underneath the obj's + hierarchy and which are not in a label for or labelled by + relation. + """ + result = [] + visibleOnly = not self._script.utilities.isStatusBarNotification(obj) + + minimumWords = 1 + role = args.get('role', AXObject.get_role(obj)) + if role in [Atspi.Role.DIALOG, Atspi.Role.PANEL]: + minimumWords = 3 + + labels = self._script.utilities.unrelatedLabels(obj, visibleOnly, minimumWords) + for label in labels: + name = self._generateName(label, **args) + if name and len(name[0]) == 1: + charname = chnames.getCharacterName(name[0]) + if charname: + name[0] = charname + result.extend(name) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + ##################################################################### + # # + # State information # + # # + ##################################################################### + + def _generateCheckedState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes. [[[WDW - should we return an empty array if + we can guarantee we know this thing is not checkable?]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateCheckedState(self, obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateExpandableState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the expanded/collapsed state of an object, such as a + tree node. If the object is not expandable, an empty array + will be returned. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateExpandableState(self, obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateCheckedStateIfCheckable(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = super()._generateCheckedStateIfCheckable(obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateMenuItemCheckedState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the menu item, only if it is + checked. Otherwise, and empty array will be returned. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator.\ + _generateMenuItemCheckedState(self, obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateMultiselectableState(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the multiselectable state of + the object. This is typically for list boxes. If the object + is not multiselectable, an empty array will be returned. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = super()._generateMultiselectableState(obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateRadioState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes. [[[WDW - should we return an empty array if + we can guarantee we know this thing is not checkable?]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateRadioState(self, obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateSwitchState(self, obj, **args): + """Returns an array of strings indicating the on/off state of obj.""" + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateSwitchState(self, obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + def _generateToggleState(self, obj, **args): + """Returns an array of strings for use by speech and braille that + represent the checked state of the object. This is typically + for check boxes. [[[WDW - should we return an empty array if + we can guarantee we know this thing is not checkable?]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = generator.Generator._generateToggleState(self, obj, **args) + if result: + result.extend(self.voice(STATE, obj=obj, **args)) + return result + + ##################################################################### + # # + # Link information # + # # + ##################################################################### + + def _generateLinkInfo(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the protocol of the URI of + the link associated with obj. + """ + result = [] + # Get the URI for the link of interest and parse it. The parsed + # URI is returned as a tuple containing six components: + # scheme://netloc/path;parameters?query#fragment. + # + link_uri = self._script.utilities.uri(obj) + if not link_uri: + # [[[TODO - JD: For some reason, this is failing for certain + # links. The current whereAmI code says, "It might be an anchor. + # Try to speak the text." and passes things off to whereAmI's + # _speakText method. That won't work in the new world order. + # Therefore, for now, I will hack in some code to do that + # work here so that the before and after end results match.]]] + # + result.extend(self._generateLabel(obj)) + result.extend(self._generateRoleName(obj)) + result.append(self._script.utilities.displayedText(obj)) + else: + link_uri_info = urllib.parse.urlparse(link_uri) + if link_uri_info[0] in ["ftp", "ftps", "file"]: + fileName = link_uri_info[2].split('/') + result.append(messages.LINK_TO_FILE \ + % {"uri" : link_uri_info[0], + "file" : fileName[-1]}) + else: + linkOutput = messages.LINK_WITH_PROTOCOL % link_uri_info[0] + text = self._script.utilities.displayedText(obj) + isVisited = AXUtilities.is_visited(obj) + if not isVisited: + linkOutput = messages.LINK_WITH_PROTOCOL % link_uri_info[0] + else: + linkOutput = messages.LINK_WITH_PROTOCOL_VISITED % link_uri_info[0] + if not text: + # If there's no text for the link, expose part of the + # URI to the user. + # + text = self._script.utilities.linkBasename(obj) + if text: + linkOutput += " " + text + result.append(linkOutput) + child = AXObject.get_child(obj, 0) + if AXUtilities.is_image(child): + result.extend(self._generateRoleName(child)) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateSiteDescription(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that describe the site (same or different) + pointed to by the URI of the link associated with obj. + """ + result = [] + link_uri = self._script.utilities.uri(obj) + if link_uri: + link_uri_info = urllib.parse.urlparse(link_uri) + else: + return result + doc_uri = self._script.utilities.documentFrameURI() + if doc_uri: + doc_uri_info = urllib.parse.urlparse(doc_uri) + if link_uri_info[1] == doc_uri_info[1]: + if link_uri_info[2] == doc_uri_info[2]: + result.append(messages.LINK_SAME_PAGE) + else: + result.append(messages.LINK_SAME_SITE) + else: + # check for different machine name on same site + # + linkdomain = link_uri_info[1].split('.') + docdomain = doc_uri_info[1].split('.') + if len(linkdomain) > 1 and len(docdomain) > 1 \ + and linkdomain[-1] == docdomain[-1] \ + and linkdomain[-2] == docdomain[-2]: + result.append(messages.LINK_SAME_SITE) + else: + result.append(messages.LINK_DIFFERENT_SITE) + + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateFileSize(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the size (Content-length) of + the file pointed to by the URI of the link associated with + obj. + """ + result = [] + sizeString = "" + uri = self._script.utilities.uri(obj) + if not uri: + return result + try: + x = urllib.request.urlopen(uri) + try: + sizeString = x.info()['Content-length'] + except KeyError: + pass + except (ValueError, urllib.error.URLError, OSError): + pass + if sizeString: + size = int(sizeString) + if size < 10000: + result.append(messages.fileSizeBytes(size)) + elif size < 1000000: + result.append(messages.FILE_SIZE_KB % (float(size) * .001)) + elif size >= 1000000: + result.append(messages.FILE_SIZE_MB % (float(size) * .000001)) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + ##################################################################### + # # + # Image information # + # # + ##################################################################### + + def _generateImage(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the image on the object, if + it exists. Otherwise, an empty array is returned. + """ + result = [] + try: + obj.queryImage() + except Exception: + pass + else: + args['role'] = Atspi.Role.IMAGE + result.extend(self.generate(obj, **args)) + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + ##################################################################### + # # + # Table interface information # + # # + ##################################################################### + + def _generateColumnHeader(self, obj, **args): + if self._script.inSayAll(): + return [] + + result = super()._generateColumnHeader(obj, **args) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + + return result + + def _generateRowHeader(self, obj, **args): + if self._script.inSayAll(): + return [] + + result = super()._generateRowHeader(obj, **args) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + + return result + + def _generateSortOrder(self, obj, **args): + result = super()._generateSortOrder(obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _generateNewRowHeader(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the row header for an object + that is in a table, if it exists and if it is different from + the previous row header. Otherwise, an empty array is + returned. The previous row header is determined by looking at + the row header for the 'priorObj' attribute of the args + dictionary. The 'priorObj' is typically set by Cthulhu to be the + previous object with focus. + """ + + if not self._script.utilities.cellRowChanged(obj): + return [] + + if args.get('readingRow'): + return [] + + if not _settingsManager.getSetting('speakCellHeaders'): + return [] + + if args.get('inMouseReview') and args.get('priorObj'): + thisrow, thiscol = self._script.utilities.coordinatesForCell(obj) + lastrow, lastcol = self._script.utilities.coordinatesForCell(args.get('priorObj')) + if thisrow == lastrow: + return [] + + args['newOnly'] = True + return self._generateRowHeader(obj, **args) + + def _generateNewColumnHeader(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the column header for an object + that is in a table, if it exists and if it is different from + the previous column header. Otherwise, an empty array is + returned. The previous column header is determined by looking + at the column header for the 'priorObj' attribute of the args + dictionary. The 'priorObj' is typically set by Cthulhu to be the + previous object with focus. + """ + + if not self._script.utilities.cellColumnChanged(obj): + return [] + + if args.get('readingRow'): + return [] + + if not _settingsManager.getSetting('speakCellHeaders'): + return [] + + if args.get('inMouseReview') and args.get('priorObj'): + thisrow, thiscol = self._script.utilities.coordinatesForCell(obj) + lastrow, lastcol = self._script.utilities.coordinatesForCell(args.get('priorObj')) + if thiscol == lastcol: + return [] + + args['newOnly'] = True + return self._generateColumnHeader(obj, **args) + + def _generateRealTableCell(self, obj, **args): + """Cthulhu has a feature to automatically read an entire row of a table + as the user arrows up/down the roles. This leads to complexity in + the code. This method is used to return an array of strings + (and possibly voice and audio specifications) for a single table + cell itself. The string, 'blank', is added for empty cells. + """ + result = [] + oldRole = self._overrideRole('REAL_ROLE_TABLE_CELL', args) + result.extend(self.generate(obj, **args)) + self._restoreRole(oldRole, args) + if not (result and result[0]) \ + and _settingsManager.getSetting('speakBlankLines') \ + and not args.get('readingRow', False) \ + and args.get('formatType') != 'ancestor': + result.append(messages.BLANK) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + + return result + + def _generateUnselectedStateIfSelectable(self, obj, **args): + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if args.get('inMouseReview'): + return [] + + if not obj: + return [] + + if not AXObject.supports_selection(AXObject.get_parent(obj)): + return [] + + if AXUtilities.is_selected(obj): + return [] + + result = [object_properties.STATE_UNSELECTED_LIST_ITEM] + result.extend(self.voice(STATE, obj=obj, **args)) + + return result + + def _generateUnselectedCell(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) if this is an icon within an layered pane or a + table cell within a table or a tree table and the item is + focused but not selected. Otherwise, an empty array is + returned. [[[WDW - I wonder if this string should be moved to + settings.py.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if args.get('inMouseReview'): + return [] + + if not obj: + return [] + + parent = AXObject.get_parent(obj) + if not AXObject.supports_selection(parent): + return [] + + if AXUtilities.is_selected(obj): + return [] + + if AXUtilities.is_text(obj): + return [] + + table = self._script.utilities.getTable(obj) + if table: + lastKey, mods = self._script.utilities.lastKeyAndModifiers() + if lastKey in ["Left", "Right"]: + return [] + if self._script.utilities.isLayoutOnly(table): + return [] + elif AXUtilities.is_layered_pane(parent): + if obj in self._script.utilities.selectedChildren(parent): + return [] + else: + return [] + + result = [object_properties.STATE_UNSELECTED_TABLE_CELL] + result.extend(self.voice(STATE, obj=obj, **args)) + + return result + + def _generateNewColumn(self, obj, **args): + if not self._script.utilities.cellColumnChanged(obj): + return [] + + if args.get('readingRow'): + return [] + + if not _settingsManager.getSetting('speakCellCoordinates'): + return [] + + return self._generateColumn(obj, **args) + + def _generateColumn(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) reflecting the column number of a cell. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + col = -1 + parent = AXObject.get_parent(obj) + if AXUtilities.is_table_cell(parent): + obj = parent + parent = self._script.utilities.getTable(obj) + try: + table = parent.queryTable() + except Exception: + if args.get('guessCoordinates', False): + col = self._script.pointOfReference.get('lastColumn', -1) + else: + index = self._script.utilities.cellIndex(obj) + col = table.getColumnAtIndex(index) + if col >= 0: + result.append(messages.TABLE_COLUMN % (col + 1)) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateNewRow(self, obj, **args): + if not self._script.utilities.cellRowChanged(obj): + return [] + + if args.get('readingRow'): + return [] + + if not _settingsManager.getSetting('speakCellCoordinates'): + return [] + + return self._generateRow(obj, **args) + + def _generateRow(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) reflecting the row number of a cell. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + row = -1 + parent = AXObject.get_parent(obj) + if AXUtilities.is_table_cell(parent): + obj = parent + parent = self._script.utilities.getTable(obj) + try: + table = parent.queryTable() + except Exception: + if args.get('guessCoordinates', False): + row = self._script.pointOfReference.get('lastRow', -1) + else: + index = self._script.utilities.cellIndex(obj) + row = table.getRowAtIndex(index) + if row >= 0: + result.append(messages.TABLE_ROW % (row + 1)) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateColumnAndRow(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) reflecting the position of the cell in terms + of its column number, the total number of columns, its row, + and the total number of rows. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + parent = AXObject.get_parent(obj) + if AXUtilities.is_table_cell(parent): + obj = parent + parent = self._script.utilities.getTable(obj) + try: + table = parent.queryTable() + except Exception: + table = None + else: + index = self._script.utilities.cellIndex(obj) + col = table.getColumnAtIndex(index) + row = table.getRowAtIndex(index) + result.append(messages.TABLE_COLUMN_DETAILED \ + % {"index" : (col + 1), + "total" : table.nColumns}) + result.append(messages.TABLE_ROW_DETAILED \ + % {"index" : (row + 1), + "total" : table.nRows}) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateEndOfTableIndicator(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) indicating that this cell is the last cell + in the table. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if _settingsManager.getSetting('speechVerbosityLevel') \ + != settings.VERBOSITY_LEVEL_VERBOSE: + return [] + + if self._script.utilities.isLastCell(obj): + result = [messages.TABLE_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + return [] + + ##################################################################### + # # + # Text interface information # + # # + ##################################################################### + + def _generateCurrentLineText(self, obj, **args): + """Returns an array of strings for use by speech and braille + that represents the current line of text, if + this is a text object. [[[WDW - consider returning an empty + array if this is not a text object.]]] + """ + + if args.get('inMouseReview') \ + and AXUtilities.is_editable(obj): + return [] + + result = self._generateSubstring(obj, **args) + if result and result[0]: + return result + + [text, caretOffset, startOffset] = self._script.getTextLineAtCaret(obj) + if text == '\n' and _settingsManager.getSetting('speakBlankLines') \ + and not self._script.inSayAll() and args.get('total', 1) == 1 \ + and args.get('formatType') != 'ancestor': + result = [messages.BLANK] + result.extend(self.voice(string=text, obj=obj, **args)) + return result + + result = [] + endOffset = startOffset + len(text) + split = self._script.utilities.splitSubstringByLanguage(obj, startOffset, endOffset) + for start, end, string, language, dialect in split: + string = string.replace(self._script.EMBEDDED_OBJECT_CHARACTER, "") + if not string: + continue + args["language"], args["dialect"] = language, dialect + if "string" in args: + msg = f"INFO: Found existing string '{args.get('string')}'; using '{string}'" + debug.printMessage(debug.LEVEL_INFO, msg, True) + args.pop("string") + + voice = self.voice(string=string, obj=obj, **args) + string = self._script.utilities.adjustForLinks(obj, string, start) + rv = [self._script.utilities.adjustForRepeats(string)] + rv.extend(voice) + + # TODO - JD: speech.speak() has a bug which causes a list of utterances to + # be presented before a string+voice pair that comes first. Until we can + # fix speak() properly, we'll avoid triggering it here. + # result.append(rv) + result.extend(rv) + + return result + + def _generateDisplayedText(self, obj, **args): + result = self._generateSubstring(obj, **args) + if result and result[0]: + return result + + result = generator.Generator._generateDisplayedText(self, obj, **args) + if not (result and result[0]): + return [] + + string = result[0].strip() + if len(string) == 1 and self._script.utilities.isMath(obj): + charname = chnames.getCharacterName(string, preferMath=True) + if charname != string: + result[0] = charname + + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + def _getCharacterAttributes(self, + obj, + text, + textOffset, + lineIndex, + keys=["style", "weight", "underline"]): + """Helper function that returns a string containing the + given attributes from keys for the given character. + """ + attribStr = "" + + defaultAttributes = text.getDefaultAttributes() + keyList, attributesDictionary = \ + self._script.utilities.stringToKeysAndDict(defaultAttributes) + + charAttributes = text.getAttributes(textOffset) + if charAttributes[0]: + keyList, charDict = \ + self._script.utilities.stringToKeysAndDict(charAttributes[0]) + for key in keyList: + attributesDictionary[key] = charDict[key] + + if attributesDictionary: + for key in keys: + localizedKey = text_attribute_names.getTextAttributeName( + key, self._script) + if key in attributesDictionary: + attribute = attributesDictionary[key] + localizedValue = text_attribute_names.getTextAttributeName( + attribute, self._script) + if attribute: + # If it's the 'weight' attribute and greater than 400, + # just speak it as bold, otherwise speak the weight. + # + if key == "weight": + if int(attribute) > 400: + attribStr += f" {messages.BOLD}" + elif key == "underline": + if attribute != "none": + attribStr += f" {localizedKey}" + elif key == "style": + if attribute != "normal": + attribStr += f" {localizedValue}" + else: + attribStr += " " + attribStr += (localizedKey + " " + localizedValue) + + # Also check to see if this is a hypertext link. + # + if self._script.utilities.linkIndex(obj, textOffset) >= 0: + attribStr += f" {messages.LINK}" + + return attribStr + + def _getTextInformation(self, obj): + """Returns [textContents, startOffset, endOffset, selected] as + follows: + + A. if no text on the current line is selected, the current line + B. if text is selected, the selected text + C. if the current line is blank/empty, 'blank' + + Also sets up a 'textInformation' attribute in + self._script.generatorCache to prevent computing this + information repeatedly while processing a single event. + """ + + try: + return self._script.generatorCache['textInformation'] + except Exception: + pass + + textObj = obj.queryText() + caretOffset = textObj.caretOffset + + textContents, startOffset, endOffset = self._script.utilities.allSelectedText(obj) + selected = textContents != "" + + if not selected: + # Get the line containing the caret + # + [line, startOffset, endOffset] = textObj.getTextAtOffset( + textObj.caretOffset, + Atspi.TextBoundaryType.LINE_START) + if len(line): + line = self._script.utilities.adjustForRepeats(line) + textContents = line + else: + char = textObj.getTextAtOffset(caretOffset, + Atspi.TextBoundaryType.CHAR) + if char[0] == "\n" and startOffset == caretOffset: + textContents = char[0] + + if self._script.utilities.shouldVerbalizeAllPunctuation(obj): + textContents = self._script.utilities.verbalizeAllPunctuation(textContents) + + self._script.generatorCache['textInformation'] = \ + [textContents, startOffset, endOffset, selected] + + return self._script.generatorCache['textInformation'] + + def _generateTextContent(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) containing the text content. This requires + _generateTextInformation to have been called prior to this method. + """ + + result = self._generateSubstring(obj, **args) + if result: + return result + + try: + obj.queryText() + except NotImplementedError: + return [] + + result = [] + [line, startOffset, endOffset, selected] = self._getTextInformation(obj) + + # The empty string seems to be messing with using 'or' in + # formatting strings. + # + if line: + result.append(line) + result.extend(self.voice(DEFAULT, obj=obj, **args)) + + return result + + def _generateTextContentWithAttributes(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) containing the text content, obtained from the + 'textInformation' value, with character attribute information + mixed in. This requires _generateTextInformation to have been + called prior to this method. + """ + + try: + text = obj.queryText() + except NotImplementedError: + return [] + + [line, startOffset, endOffset, selected] = self._getTextInformation(obj) + + newLine = "" + lastAttribs = None + textOffset = startOffset + for i in range(0, len(line)): + attribs = self._getCharacterAttributes(obj, text, textOffset, i) + if attribs and attribs != lastAttribs: + if newLine: + newLine += " ; " + newLine += attribs + newLine += " " + lastAttribs = attribs + newLine += line[i] + textOffset += 1 + + attribs = self._getCharacterAttributes(obj, + text, + startOffset, + 0, + ["paragraph-style"]) + + if attribs: + if newLine: + newLine += " ; " + newLine += attribs + + result = [newLine] + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + def _generateAnyTextSelection(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that says if any of the text for the entire + object is selected. [[[WDW - I wonder if this string should be + moved to settings.py.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + try: + obj.queryText() + except NotImplementedError: + return [] + + result = [] + [line, startOffset, endOffset, selected] = self._getTextInformation(obj) + + if selected: + result.append(messages.TEXT_SELECTED) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateAllTextSelection(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that says if all the text for the entire + object is selected. [[[WDW - I wonder if this string should be + moved to settings.py.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + try: + textObj = obj.queryText() + except Exception: + pass + else: + noOfSelections = textObj.getNSelections() + if noOfSelections == 1: + [string, startOffset, endOffset] = \ + textObj.getTextAtOffset(0, Atspi.TextBoundaryType.LINE_START) + if startOffset == 0 and endOffset == len(string): + result = [messages.TEXT_SELECTED] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateSubstring(self, obj, **args): + result = super()._generateSubstring(obj, **args) + if not (result and result[0]): + return [] + + result.extend(self.voice(DEFAULT, obj=obj, **args)) + if result[0] in ['\n', ''] and _settingsManager.getSetting('speakBlankLines') \ + and not self._script.inSayAll() and args.get('total', 1) == 1 \ + and args.get('formatType') != 'ancestor': + result[0] = messages.BLANK + + if self._script.utilities.shouldVerbalizeAllPunctuation(obj): + result[0] = self._script.utilities.verbalizeAllPunctuation(result[0]) + + return result + + def _generateTextIndentation(self, obj, **args): + """Speaks a summary of the number of spaces and/or tabs at the + beginning of the given line. + + Arguments: + - obj: the text object. + """ + + if not _settingsManager.getSetting('enableSpeechIndentation'): + return [] + + line, caretOffset, startOffset = self._script.getTextLineAtCaret(obj) + description = self._script.utilities.indentationDescription(line) + if not description: + return [] + + result = [description] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateNestingLevel(self, obj, **args): + result = super()._generateNestingLevel(obj, **args) + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + ##################################################################### + # # + # Tree interface information # + # # + ##################################################################### + + def _generateNewNodeLevel(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represents the tree node level of the + object, or an empty array if the object is not a tree node or + if the node level is not different from the 'priorObj' + 'priorObj' attribute of the args dictionary. The 'priorObj' + is typically set by Cthulhu to be the previous object with + focus. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + oldLevel = self._script.utilities.nodeLevel(args.get('priorObj', None)) + newLevel = self._script.utilities.nodeLevel(obj) + if (oldLevel != newLevel) and (newLevel >= 0): + result.extend(self._generateNodeLevel(obj, **args)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + ##################################################################### + # # + # Value interface information # + # # + ##################################################################### + + def _generateValue(self, obj, **args): + result = super()._generateValue(obj, **args) + if result: + result.extend(self.voice(DEFAULT, obj=obj, **args)) + + return result + + def _generatePercentage(self, obj, **args ): + """Returns an array of strings (and possibly voice and audio + specifications) that represents the percentage value of the + object. This is typically for progress bars. [[[WDW - we + should consider returning an empty array if there is no value. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + percentValue = self._script.utilities.getValueAsPercent(obj) + if percentValue is not None: + result = [messages.percentage(percentValue)] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + return [] + + ##################################################################### + # # + # Hierarchy and related dialog information # + # # + ##################################################################### + + def _generateNewRadioButtonGroup(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represents the radio button group label + of the object, or an empty array if the object has no such + label or if the radio button group is not different from the + 'priorObj' 'priorObj' attribute of the args dictionary. The + 'priorObj' is typically set by Cthulhu to be the previous object + with focus. + """ + + if not AXUtilities.is_radio_button(obj): + return [] + + result = super()._generateRadioButtonGroup(obj, **args) + if not result: + return [] + + result.extend(self.voice(DEFAULT, obj=obj, **args)) + priorObj = args.get('priorObj', None) + if not AXUtilities.is_radio_button(priorObj): + return result + + # TODO - JD: We need other ways to determine group membership. Not all + # implementations expose the member-of relation. Gtk3 does. Others are TBD. + members = AXObject.get_relation_targets(obj, Atspi.RelationType.MEMBER_OF) + if priorObj not in members: + return result + + return [] + + def _generateTermValueCount(self, obj, **args): + count = self._script.utilities.getValueCountForTerm(obj) + # If we have a simple 1-term, 1-value situation, this announcment is chatty. + if count in (-1, 1): + return [] + + result = [messages.valueCountForTerm(count)] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateNumberOfChildren(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represents the number of children the + object has. [[[WDW - can we always return an empty array if + this doesn't apply?]]] [[[WDW - I wonder if this string should + be moved to settings.py.]]] + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or _settingsManager.getSetting('speechVerbosityLevel') == settings.VERBOSITY_LEVEL_BRIEF: + return [] + + result = [] + childNodes = self._script.utilities.childNodes(obj) + children = len(childNodes) + if children: + result.append(messages.itemCount(children)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + role = args.get('role', AXObject.get_role(obj)) + if role in [Atspi.Role.LIST, Atspi.Role.LIST_BOX]: + children = [x for x in AXObject.iter_children(obj, AXUtilities.is_list_item)] + setsize = len(children) + if not setsize: + return [] + + result = [messages.listItemCount(setsize)] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _generateNoShowingChildren(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that says if this object has no showing + children (e.g., it's an empty table or list). object has. + [[[WDW - can we always return an empty array if this doesn't + apply?]]] [[[WDW - I wonder if this string should be moved to + settings.py.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + hasItems = any(True for _ in AXObject.iter_children(obj, AXUtilities.is_showing)) + if not hasItems: + result.append(messages.ZERO_ITEMS) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateNoChildren(self, obj, **args ): + """Returns an array of strings (and possibly voice and audio + specifications) that says if this object has no children at + all (e.g., it's an empty table or list). object has. [[[WDW + - can we always return an empty array if this doesn't + apply?]]] [[[WDW - I wonder if this string should be moved to + settings.py.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + if not AXObject.get_child_count(obj): + result.append(messages.ZERO_ITEMS) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateFocusedItem(self, obj, **args): + result = [] + role = args.get('role', AXObject.get_role(obj)) + if role not in [Atspi.Role.LIST, Atspi.Role.LIST_BOX]: + return result + + if AXObject.supports_selection(obj): + items = self._script.utilities.selectedChildren(obj) + else: + items = [AXUtilities.get_focused_object(obj)] + if not (items and items[0]): + return result + + for item in map(self._generateName, items): + result.extend(item) + + return result + + def _generateSelectedItemCount(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) indicating how many items are selected in this + and the position of the current item. This object will be an icon + panel or a layered pane. + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + container = obj + if not AXObject.supports_selection(container): + container = AXObject.get_parent(obj) + if not AXObject.supports_selection(container): + return [] + + result = [] + childCount = AXObject.get_child_count(container) + selectedCount = len(self._script.utilities.selectedChildren(container)) + result.append(messages.selectedItemsCount(selectedCount, childCount)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.append(self._script.formatting.getString( + mode='speech', + stringType='iconindex') \ + % {"index" : AXObject.get_index_in_parent(obj) + 1, + "total" : childCount}) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateSelectedItems(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) containing the names of all the selected items. + This object will be an icon panel or a layered pane. + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + container = obj + if not AXObject.supports_selection(container): + container = AXObject.get_parent(obj) + if not AXObject.supports_selection(container): + return [] + + selectedItems = self._script.utilities.selectedChildren(container) + return list(map(self._generateLabelAndName, selectedItems)) + + def generateSelectedItems(self, obj, **args): + return self._generateSelectedItems(obj, **args) + + def _generateUnfocusedDialogCount(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that says how many unfocused alerts and + dialogs are associated with the application for this object. + [[[WDW - I wonder if this string should be moved to + settings.py.]]] + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + # If this application has more than one unfocused alert or + # dialog window, then speak ' unfocused dialogs' + # to let the user know. + # + try: + alertAndDialogCount = \ + self._script.utilities.unfocusedAlertAndDialogCount(obj) + except Exception: + alertAndDialogCount = 0 + if alertAndDialogCount > 0: + result.append(messages.dialogCountSpeech(alertAndDialogCount)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _getEnabledAndDisabledContextRoles(self): + allRoles = [Atspi.Role.BLOCK_QUOTE, + 'ROLE_CONTENT_DELETION', + 'ROLE_CONTENT_INSERTION', + 'ROLE_CONTENT_MARK', + 'ROLE_CONTENT_SUGGESTION', + 'ROLE_DPUB_LANDMARK', + 'ROLE_DPUB_SECTION', + Atspi.Role.DESCRIPTION_LIST, + 'ROLE_FEED', + Atspi.Role.FORM, + Atspi.Role.LANDMARK, + Atspi.Role.LIST, + Atspi.Role.PANEL, + 'ROLE_REGION', + Atspi.Role.TABLE, + Atspi.Role.TOOL_TIP] + + enabled, disabled = [], [] + if self._script.inSayAll(): + if _settingsManager.getSetting('sayAllContextBlockquote'): + enabled.append(Atspi.Role.BLOCK_QUOTE) + if _settingsManager.getSetting('sayAllContextLandmark'): + enabled.extend([Atspi.Role.LANDMARK, 'ROLE_DPUB_LANDMARK']) + if _settingsManager.getSetting('sayAllContextList'): + enabled.append(Atspi.Role.LIST) + enabled.append(Atspi.Role.DESCRIPTION_LIST) + enabled.append('ROLE_FEED') + if _settingsManager.getSetting('sayAllContextPanel'): + enabled.extend([Atspi.Role.PANEL, + Atspi.Role.TOOL_TIP, + 'ROLE_CONTENT_DELETION', + 'ROLE_CONTENT_INSERTION', + 'ROLE_CONTENT_MARK', + 'ROLE_CONTENT_SUGGESTION', + 'ROLE_DPUB_SECTION']) + if _settingsManager.getSetting('sayAllContextNonLandmarkForm'): + enabled.append(Atspi.Role.FORM) + if _settingsManager.getSetting('sayAllContextTable'): + enabled.append(Atspi.Role.TABLE) + else: + if _settingsManager.getSetting('speakContextBlockquote'): + enabled.append(Atspi.Role.BLOCK_QUOTE) + if _settingsManager.getSetting('speakContextLandmark'): + enabled.extend([Atspi.Role.LANDMARK, 'ROLE_DPUB_LANDMARK', 'ROLE_REGION']) + if _settingsManager.getSetting('speakContextList'): + enabled.append(Atspi.Role.LIST) + enabled.append(Atspi.Role.DESCRIPTION_LIST) + enabled.append('ROLE_FEED') + if _settingsManager.getSetting('speakContextPanel'): + enabled.extend([Atspi.Role.PANEL, + Atspi.Role.TOOL_TIP, + 'ROLE_CONTENT_DELETION', + 'ROLE_CONTENT_INSERTION', + 'ROLE_CONTENT_MARK', + 'ROLE_CONTENT_SUGGESTION', + 'ROLE_DPUB_SECTION']) + if _settingsManager.getSetting('speakContextNonLandmarkForm'): + enabled.append(Atspi.Role.FORM) + if _settingsManager.getSetting('speakContextTable'): + enabled.append(Atspi.Role.TABLE) + + disabled = list(set(allRoles).symmetric_difference(enabled)) + return enabled, disabled + + def _generateLeaving(self, obj, **args): + if not args.get('leaving'): + return [] + + role = args.get('role', AXObject.get_role(obj)) + enabled, disabled = self._getEnabledAndDisabledContextRoles() + if not (role in enabled or self._script.utilities.isDetails(obj)): + return [] + + count = args.get('count', 1) + + result = [] + if self._script.utilities.isDetails(obj): + result.append(messages.LEAVING_DETAILS) + elif role == Atspi.Role.BLOCK_QUOTE: + if count > 1: + result.append(messages.leavingNBlockquotes(count)) + else: + result.append(messages.LEAVING_BLOCKQUOTE) + elif role in [Atspi.Role.LIST, Atspi.Role.DESCRIPTION_LIST] \ + and self._script.utilities.isDocumentList(obj): + if count > 1: + result.append(messages.leavingNLists(count)) + else: + result.append(messages.LEAVING_LIST) + elif role == 'ROLE_FEED': + result.append(messages.LEAVING_FEED) + elif role == Atspi.Role.PANEL: + if self._script.utilities.isFigure(obj): + result.append(messages.LEAVING_FIGURE) + elif self._script.utilities.isDocumentPanel(obj): + result.append(messages.LEAVING_PANEL) + else: + result = [''] + elif role == Atspi.Role.TABLE and self._script.utilities.isTextDocumentTable(obj): + result.append(messages.LEAVING_TABLE) + elif role == 'ROLE_DPUB_LANDMARK': + if self._script.utilities.isDPubAcknowledgments(obj): + result.append(messages.LEAVING_ACKNOWLEDGMENTS) + elif self._script.utilities.isDPubAfterword(obj): + result.append(messages.LEAVING_AFTERWORD) + elif self._script.utilities.isDPubAppendix(obj): + result.append(messages.LEAVING_APPENDIX) + elif self._script.utilities.isDPubBibliography(obj): + result.append(messages.LEAVING_BIBLIOGRAPHY) + elif self._script.utilities.isDPubChapter(obj): + result.append(messages.LEAVING_CHAPTER) + elif self._script.utilities.isDPubConclusion(obj): + result.append(messages.LEAVING_CONCLUSION) + elif self._script.utilities.isDPubCredits(obj): + result.append(messages.LEAVING_CREDITS) + elif self._script.utilities.isDPubEndnotes(obj): + result.append(messages.LEAVING_ENDNOTES) + elif self._script.utilities.isDPubEpilogue(obj): + result.append(messages.LEAVING_EPILOGUE) + elif self._script.utilities.isDPubErrata(obj): + result.append(messages.LEAVING_ERRATA) + elif self._script.utilities.isDPubForeword(obj): + result.append(messages.LEAVING_FOREWORD) + elif self._script.utilities.isDPubGlossary(obj): + result.append(messages.LEAVING_GLOSSARY) + elif self._script.utilities.isDPubIndex(obj): + result.append(messages.LEAVING_INDEX) + elif self._script.utilities.isDPubIntroduction(obj): + result.append(messages.LEAVING_INTRODUCTION) + elif self._script.utilities.isDPubPagelist(obj): + result.append(messages.LEAVING_PAGELIST) + elif self._script.utilities.isDPubPart(obj): + result.append(messages.LEAVING_PART) + elif self._script.utilities.isDPubPreface(obj): + result.append(messages.LEAVING_PREFACE) + elif self._script.utilities.isDPubPrologue(obj): + result.append(messages.LEAVING_PROLOGUE) + elif self._script.utilities.isDPubToc(obj): + result.append(messages.LEAVING_TOC) + elif role == 'ROLE_DPUB_SECTION': + if self._script.utilities.isDPubAbstract(obj): + result.append(messages.LEAVING_ABSTRACT) + elif self._script.utilities.isDPubColophon(obj): + result.append(messages.LEAVING_COLOPHON) + elif self._script.utilities.isDPubCredit(obj): + result.append(messages.LEAVING_CREDIT) + elif self._script.utilities.isDPubDedication(obj): + result.append(messages.LEAVING_DEDICATION) + elif self._script.utilities.isDPubEpigraph(obj): + result.append(messages.LEAVING_EPIGRAPH) + elif self._script.utilities.isDPubExample(obj): + result.append(messages.LEAVING_EXAMPLE) + elif self._script.utilities.isDPubPullquote(obj): + result.append(messages.LEAVING_PULLQUOTE) + elif self._script.utilities.isDPubQna(obj): + result.append(messages.LEAVING_QNA) + elif self._script.utilities.isLandmark(obj): + if self._script.utilities.isLandmarkBanner(obj): + result.append(messages.LEAVING_LANDMARK_BANNER) + elif self._script.utilities.isLandmarkComplementary(obj): + result.append(messages.LEAVING_LANDMARK_COMPLEMENTARY) + elif self._script.utilities.isLandmarkContentInfo(obj): + result.append(messages.LEAVING_LANDMARK_CONTENTINFO) + elif self._script.utilities.isLandmarkMain(obj): + result.append(messages.LEAVING_LANDMARK_MAIN) + elif self._script.utilities.isLandmarkNavigation(obj): + result.append(messages.LEAVING_LANDMARK_NAVIGATION) + elif self._script.utilities.isLandmarkRegion(obj): + result.append(messages.LEAVING_LANDMARK_REGION) + elif self._script.utilities.isLandmarkSearch(obj): + result.append(messages.LEAVING_LANDMARK_SEARCH) + elif self._script.utilities.isLandmarkForm(obj): + result.append(messages.LEAVING_FORM) + else: + result = [''] + elif role == Atspi.Role.FORM: + result.append(messages.LEAVING_FORM) + elif role == Atspi.Role.TOOL_TIP: + result.append(messages.LEAVING_TOOL_TIP) + elif role == 'ROLE_CONTENT_DELETION': + result.append(messages.CONTENT_DELETION_END) + elif role == 'ROLE_CONTENT_INSERTION': + result.append(messages.CONTENT_INSERTION_END) + elif role == 'ROLE_CONTENT_MARK': + result.append(messages.CONTENT_MARK_END) + elif role == 'ROLE_CONTENT_SUGGESTION' \ + and not self._script.utilities.isInlineSuggestion(obj): + result.append(messages.LEAVING_SUGGESTION) + else: + result = [''] + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _generateAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object. This is typically used to present the context for + an object (e.g., the names of the window, the panels, etc., + that the object is contained in). If the 'priorObj' attribute + of the args dictionary is set, only the differences in + ancestry between the 'priorObj' and the current obj will be + computed. The 'priorObj' is typically set by Cthulhu to be the + previous object with focus. + """ + result = [] + + leaving = args.get('leaving') + if leaving and args.get('priorObj'): + priorObj = obj + obj = args.get('priorObj') + else: + priorObj = args.get('priorObj') + + if priorObj and AXObject.is_dead(priorObj): + return [] + + if AXUtilities.is_tool_tip(priorObj): + return [] + + if priorObj and AXObject.get_parent(priorObj) == AXObject.get_parent(obj): + return [] + + if self._script.utilities.isTypeahead(priorObj): + return [] + + if AXUtilities.is_page_tab(obj): + return [] + + if AXUtilities.is_tool_tip(obj): + return [] + + commonAncestor = self._script.utilities.commonAncestor(priorObj, obj) + if obj == commonAncestor: + return [] + + includeOnly = args.get('includeOnly', []) + + skipRoles = args.get('skipRoles', []) + skipRoles.append(Atspi.Role.TREE_ITEM) + enabled, disabled = self._getEnabledAndDisabledContextRoles() + skipRoles.extend(disabled) + + stopAtRoles = args.get('stopAtRoles', []) + stopAtRoles.extend([Atspi.Role.APPLICATION, Atspi.Role.MENU_BAR]) + + stopAfterRoles = args.get('stopAfterRoles', []) + stopAfterRoles.extend([Atspi.Role.TOOL_TIP]) + + presentOnce = [Atspi.Role.BLOCK_QUOTE, Atspi.Role.LIST] + + presentCommonAncestor = False + if commonAncestor and not leaving: + commonRole = self._getAlternativeRole(commonAncestor) + if commonRole in presentOnce: + def pred(x): + return self._getAlternativeRole(x) == commonRole + objAncestor = AXObject.find_ancestor(obj, pred) + priorAncestor = AXObject.find_ancestor(priorObj, pred) + objLevel = self._script.utilities.nestingLevel(objAncestor) + priorLevel = self._script.utilities.nestingLevel(priorAncestor) + presentCommonAncestor = objLevel != priorLevel + + ancestors, ancestorRoles = [], [] + parent = AXObject.get_parent_checked(obj) + while parent: + parentRole = self._getAlternativeRole(parent) + if parentRole in stopAtRoles: + break + if parentRole in skipRoles: + pass + elif includeOnly and parentRole not in includeOnly: + pass + elif self._script.utilities.isLayoutOnly(parent): + pass + elif self._script.utilities.isButtonWithPopup(parent): + pass + elif parent != commonAncestor or presentCommonAncestor: + ancestors.append(parent) + ancestorRoles.append(parentRole) + + if parent == commonAncestor or parentRole in stopAfterRoles: + break + + parent = AXObject.get_parent_checked(parent) + + presentedRoles = [] + for i, x in enumerate(ancestors): + altRole = ancestorRoles[i] + if altRole in presentOnce and altRole in presentedRoles: + continue + + presentedRoles.append(altRole) + count = ancestorRoles.count(altRole) + self._overrideRole(altRole, args) + result.append( + self.generate(x, formatType='ancestor', role=altRole, + leaving=leaving, count=count, ancestorOf=obj, priorObj=priorObj)) + self._restoreRole(altRole, args) + + if not leaving: + result.reverse() + return result + + def _generateOldAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object being left.""" + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if self._script.utilities.inFindContainer(): + return [] + + priorObj = args.get('priorObj') + if not priorObj or obj == priorObj or self._script.utilities.isZombie(priorObj): + return [] + + if AXUtilities.is_page_tab(obj): + return [] + + if AXObject.get_application(obj) != AXObject.get_application(priorObj) \ + or AXObject.find_ancestor(obj, lambda x: x == priorObj): + return [] + + frame, dialog = self._script.utilities.frameAndDialog(obj) + if dialog: + return [] + + args['leaving'] = True + args['includeOnly'] = [Atspi.Role.BLOCK_QUOTE, + Atspi.Role.DESCRIPTION_LIST, + Atspi.Role.FORM, + Atspi.Role.LANDMARK, + 'ROLE_CONTENT_DELETION', + 'ROLE_CONTENT_INSERTION', + 'ROLE_CONTENT_MARK', + 'ROLE_CONTENT_SUGGESTION', + 'ROLE_DPUB_LANDMARK', + 'ROLE_DPUB_SECTION', + 'ROLE_FEED', + Atspi.Role.LIST, + Atspi.Role.PANEL, + 'ROLE_REGION', + Atspi.Role.TABLE, + Atspi.Role.TOOL_TIP] + + result = [] + if self._script.utilities.isBlockquote(priorObj): + oldRole = self._getAlternativeRole(priorObj) + self._overrideRole(oldRole, args) + result.extend(self.generate( + priorObj, role=oldRole, formatType='focused', leaving=True)) + self._restoreRole(oldRole, args) + + result.extend(self._generateAncestors(obj, **args)) + args.pop('leaving') + args.pop('includeOnly') + + return result + + def _generateNewAncestors(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the text of the ancestors for + the object. This is typically used to present the context for + an object (e.g., the names of the window, the panels, etc., + that the object is contained in). If the 'priorObj' attribute + of the args dictionary is set, only the differences in + ancestry between the 'priorObj' and the current obj will be + computed. Otherwise, no ancestry will be computed. The + 'priorObj' is typically set by Cthulhu to be the previous object + with focus. + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + if self._script.utilities.inFindContainer(): + return [] + + priorObj = args.get('priorObj') + if priorObj == obj: + return [] + + role = args.get('role', AXObject.get_role(obj)) + if role in [Atspi.Role.FRAME, Atspi.Role.WINDOW]: + return [] + + if role == Atspi.Role.MENU_ITEM and (not priorObj or AXUtilities.is_window(priorObj)): + return [] + + if priorObj is not None: + return self._generateAncestors(obj, **args) + + frame, dialog = self._script.utilities.frameAndDialog(obj) + topLevel = dialog or frame + if AXUtilities.is_dialog_or_alert(topLevel): + return self._generateAncestors(obj, **args) + + return [] + + def generateContext(self, obj, **args): + if args.get('priorObj') == obj: + return [] + + result = self._generateOldAncestors(obj, **args) + result.append(self._generateNewAncestors(obj, **args)) + return result + + def _generateParentRoleName(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) containing the role name of the parent of obj. + """ + if args.get('role', AXObject.get_role(obj)) == Atspi.Role.ICON \ + and args.get('formatType', None) \ + in ['basicWhereAmI', 'detailedWhereAmI']: + return [object_properties.ROLE_ICON_PANEL] + + parent = AXObject.get_parent(obj) + if AXUtilities.is_table_cell(parent) or AXUtilities.is_menu(parent): + obj = parent + return self._generateRoleName(AXObject.get_parent(obj)) + + def _generateToolbar(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) containing the name and role of the toolbar + which contains obj. + """ + result = [] + ancestor = AXObject.find_ancestor(obj, AXUtilities.is_tool_bar) + if ancestor: + result.extend(self._generateLabelAndName(ancestor)) + result.extend(self._generateRoleName(ancestor)) + return result + + def _generatePositionInGroup(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the relative position of an + object in a group. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + # TODO - JD: We need other ways to determine group membership. Not all + # implementations expose the member-of relation. Gtk3 does. Others are TBD. + members = AXObject.get_relation_targets( + obj, Atspi.RelationType.MEMBER_OF, AXUtilities.is_showing) + if obj not in members: + return [] + + result = [] + + # TODO - JD: We used to adjust the position on the basis of this particular + # relation "tending to be given in the reverse order". But there's no reason + # that should be the case. And doesn't always appear to be the case in Gtk3. + # Until we sort out the position in group/list mess, try a more reliable + # "adjustment." + def cmp(x, y): + return AXObject.get_index_in_parent(y) - AXObject.get_index_in_parent(x) + + members = sorted(members, key=functools.cmp_to_key(cmp)) + result.append(self._script.formatting.getString( + mode='speech', + stringType='groupindex') \ + % {"index" : members.index(obj) + 1, + "total" : len(members)}) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generatePositionInList(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the relative position of an + object in a list. + """ + + if _settingsManager.getSetting('onlySpeakDisplayedText') \ + or not (_settingsManager.getSetting('enablePositionSpeaking') \ + or args.get('forceList', False)): + return [] + + if self._script.utilities.isTopLevelMenu(obj): + return [] + + if self._script.utilities.isEditableComboBox(obj): + return [] + + result = [] + position, total = self._script.utilities.getPositionAndSetSize(obj, **args) + if position < 0: + return [] + + stringType = 'groupindex' + if total < 0: + if not self._script.utilities.setSizeUnknown(obj): + return [] + stringType += 'totalunknown' + + if total == 1 and AXUtilities.is_menu(obj): + return [] + + position += 1 + result.append(self._script.formatting.getString( + mode='speech', + stringType=stringType) \ + % {"index" : position, + "total" : total}) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateProgressBarIndex(self, obj, **args): + if not args.get('isProgressBarUpdate') \ + or not self._shouldPresentProgressBarUpdate(obj, **args): + return [] + + result = [] + acc, updateTime, updateValue = self._getMostRecentProgressBarUpdate() + if acc != obj: + number, count = self.getProgressBarNumberAndCount(obj) + result = [messages.PROGRESS_BAR_NUMBER % (number)] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _generateProgressBarValue(self, obj, **args): + if args.get('isProgressBarUpdate') \ + and not self._shouldPresentProgressBarUpdate(obj, **args): + return [''] + + result = [] + percent = self._script.utilities.getValueAsPercent(obj) + if percent is not None: + result.append(messages.percentage(percent)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _getProgressBarUpdateInterval(self): + interval = _settingsManager.getSetting('progressBarSpeechInterval') + if interval is None: + interval = super()._getProgressBarUpdateInterval() + + return int(interval) + + def _shouldPresentProgressBarUpdate(self, obj, **args): + if not _settingsManager.getSetting('speakProgressBarUpdates'): + return False + + return super()._shouldPresentProgressBarUpdate(obj, **args) + + def _generateStatusBar(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the status bar of a window. + """ + + if not AXUtilities.is_status_bar(obj): + return [] + + items = self._script.utilities.statusBarItems(obj) + if not items or items == [obj]: + return [] + + result = [] + for child in items: + if child == obj: + continue + + childResult = self.generate(child, includeContext=False) + if childResult: + result.extend(childResult) + if not isinstance(childResult[-1], Pause): + result.extend(self._generatePause(child, **args)) + + return result + + def generateTitle(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the title of the window, obj. + containing the object, along with information associated with + any unfocused dialog boxes. + """ + result = [] + frame, dialog = self._script.utilities.frameAndDialog(obj) + if frame: + frameResult = self._generateLabelAndName(frame) + if not frameResult: + frameResult = self._generateRoleName(frame) + result.append(frameResult) + + if dialog: + result.append(self._generateLabelAndName(dialog)) + + alertAndDialogCount = self._script.utilities.unfocusedAlertAndDialogCount(obj) + if alertAndDialogCount > 0: + dialogs = [messages.dialogCountSpeech(alertAndDialogCount)] + dialogs.extend(self.voice(DEFAULT, obj=obj, **args)) + result.append(dialogs) + return result + + def _generateListBoxItemWidgets(self, obj, **args): + if not AXUtilities.is_list_box(AXObject.get_parent(obj)): + return [] + + result = [] + widgets = AXUtilities.get_all_widgets(obj) + for widget in widgets: + result.append(self.generate(widget, includeContext=False)) + return result + + ##################################################################### + # # + # Keyboard shortcut information # + # # + ##################################################################### + + def _generateAccelerator(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the accelerator for the object, + or an empty array if no accelerator can be found. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + [mnemonic, shortcut, accelerator] = \ + self._script.utilities.mnemonicShortcutAccelerator(obj) + if accelerator: + result.append(accelerator) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _generateMnemonic(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the mnemonic for the object, or + an empty array if no mnemonic can be found. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + if _settingsManager.getSetting('enableMnemonicSpeaking') \ + or args.get('forceMnemonic', False): + [mnemonic, shortcut, accelerator] = \ + self._script.utilities.mnemonicShortcutAccelerator(obj) + if mnemonic: + mnemonic = mnemonic[-1] # we just want a single character + if not mnemonic and shortcut: + mnemonic = shortcut + if mnemonic: + result = [mnemonic] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + ##################################################################### + # # + # Tutorial information # + # # + ##################################################################### + + def _generateTutorial(self, obj, **args): + """Returns an array of strings (and possibly voice and audio + specifications) that represent the tutorial for the object. + The tutorial will only be generated if the user has requested + tutorials, and will then be generated according to the + tutorial generator. A tutorial can be forced by setting the + 'forceTutorial' attribute of the args dictionary to True. + """ + if _settingsManager.getSetting('onlySpeakDisplayedText'): + return [] + + result = [] + alreadyFocused = args.get('alreadyFocused', False) + forceTutorial = args.get('forceTutorial', False) + role = args.get('role', AXObject.get_role(obj)) + result.extend(self._script.tutorialGenerator.getTutorial( + obj, + alreadyFocused, + forceTutorial, + role)) + if args.get('role', AXObject.get_role(obj)) == Atspi.Role.ICON \ + and args.get('formatType', 'unfocused') == 'basicWhereAmI': + frame, dialog = self._script.utilities.frameAndDialog(obj) + if frame: + result.extend(self._script.tutorialGenerator.getTutorial( + frame, + alreadyFocused, + forceTutorial)) + if result and result[0]: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + # Math + + def _generateMath(self, obj, **args): + result = [] + children = [child for child in AXObject.iter_children(obj)] + if not children and not self._script.utilities.isMathTopLevel(obj): + children = [obj] + + for child in children: + if self._script.utilities.isMathLayoutOnly(child) and AXObject.get_child_count(child): + result.extend(self._generateMath(child)) + continue + + oldRole = self._getAlternativeRole(child) + self._overrideRole(oldRole, args) + result.extend(self.generate(child, role=oldRole)) + self._restoreRole(oldRole, args) + + return result + + def _generateEnclosedBase(self, obj, **args): + return self._generateMath(obj, **args) + + def _generateEnclosedEnclosures(self, obj, **args): + strings = [] + enclosures = self._script.utilities.getMathEnclosures(obj) + if 'actuarial' in enclosures: + strings.append(messages.MATH_ENCLOSURE_ACTUARIAL) + if 'box' in enclosures: + strings.append(messages.MATH_ENCLOSURE_BOX) + if 'circle' in enclosures: + strings.append(messages.MATH_ENCLOSURE_CIRCLE) + if 'longdiv' in enclosures: + strings.append(messages.MATH_ENCLOSURE_LONGDIV) + if 'radical' in enclosures: + strings.append(messages.MATH_ENCLOSURE_RADICAL) + if 'roundedbox' in enclosures: + strings.append(messages.MATH_ENCLOSURE_ROUNDEDBOX) + if 'horizontalstrike' in enclosures: + strings.append(messages.MATH_ENCLOSURE_HORIZONTALSTRIKE) + if 'verticalstrike' in enclosures: + strings.append(messages.MATH_ENCLOSURE_VERTICALSTRIKE) + if 'downdiagonalstrike' in enclosures: + strings.append(messages.MATH_ENCLOSURE_DOWNDIAGONALSTRIKE) + if 'updiagonalstrike' in enclosures: + strings.append(messages.MATH_ENCLOSURE_UPDIAGONALSTRIKE) + if 'northeastarrow' in enclosures: + strings.append(messages.MATH_ENCLOSURE_NORTHEASTARROW) + if 'bottom' in enclosures: + strings.append(messages.MATH_ENCLOSURE_BOTTOM) + if 'left' in enclosures: + strings.append(messages.MATH_ENCLOSURE_LEFT) + if 'right' in enclosures: + strings.append(messages.MATH_ENCLOSURE_RIGHT) + if 'top' in enclosures: + strings.append(messages.MATH_ENCLOSURE_TOP) + if 'phasorangle' in enclosures: + strings.append(messages.MATH_ENCLOSURE_PHASOR_ANGLE) + if 'madruwb' in enclosures: + strings.append(messages.MATH_ENCLOSURE_MADRUWB) + if not strings: + tokens = ["SPEECH GENERATOR: Could not get enclosure message for", enclosures] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + if len(strings) == 1: + result = [messages.MATH_ENCLOSURE_ENCLOSED_BY % strings[0]] + else: + strings.insert(-1, messages.MATH_ENCLOSURE_AND) + if len(strings) == 3: + result = [messages.MATH_ENCLOSURE_ENCLOSED_BY % " ".join(strings)] + else: + result = [messages.MATH_ENCLOSURE_ENCLOSED_BY % ", ".join(strings)] + + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateFencedStart(self, obj, **args): + fenceStart, fenceEnd = self._script.utilities.getMathFences(obj) + if fenceStart: + result = [chnames.getCharacterName(fenceStart)] + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + return [] + + def _generateFencedContents(self, obj, **args): + result = [] + separators = self._script.utilities.getMathFencedSeparators(obj) + for x in range(len(separators), AXObject.get_child_count(obj)-1): + separators.append(separators[-1]) + separators.append('') + + for i, child in enumerate(obj): + result.extend(self._generateMath(child, **args)) + separatorName = chnames.getCharacterName(separators[i]) + result.append(separatorName) + result.extend(self.voice(DEFAULT, obj=obj, **args)) + if separatorName: + result.extend(self._generatePause(obj, **args)) + + return result + + def _generateFencedEnd(self, obj, **args): + fenceStart, fenceEnd = self._script.utilities.getMathFences(obj) + if fenceEnd: + result = [chnames.getCharacterName(fenceEnd)] + result.extend(self.voice(DEFAULT, obj=obj, **args)) + return result + + return [] + + def _generateFractionStart(self, obj, **args): + if self._script.utilities.isMathFractionWithoutBar(obj): + result = [messages.MATH_FRACTION_WITHOUT_BAR_START] + else: + result = [messages.MATH_FRACTION_START] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateFractionNumerator(self, obj, **args): + numerator = self._script.utilities.getMathNumerator(obj) + if self._script.utilities.isMathLayoutOnly(numerator): + return self._generateMath(numerator) + + oldRole = self._getAlternativeRole(numerator) + self._overrideRole(oldRole, args) + result = self.generate(numerator, role=oldRole) + self._restoreRole(oldRole, args) + return result + + def _generateFractionDenominator(self, obj, **args): + denominator = self._script.utilities.getMathDenominator(obj) + if self._script.utilities.isMathLayoutOnly(denominator): + return self._generateMath(denominator) + + oldRole = self._getAlternativeRole(denominator) + self._overrideRole(oldRole, args) + result = self.generate(denominator, role=oldRole) + self._restoreRole(oldRole, args) + return result + + def _generateFractionLine(self, obj, **args): + result = [messages.MATH_FRACTION_LINE] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateFractionEnd(self, obj, **args): + result = [messages.MATH_FRACTION_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateRootStart(self, obj, **args): + result = [] + if self._script.utilities.isMathSquareRoot(obj): + result = [messages.MATH_SQUARE_ROOT_OF] + else: + index = self._script.utilities.getMathRootIndex(obj) + string = self._script.utilities.displayedText(index) + if string == "2": + result = [messages.MATH_SQUARE_ROOT_OF] + elif string == "3": + result = [messages.MATH_CUBE_ROOT_OF] + elif string: + result = [string] + result.extend([messages.MATH_ROOT_OF]) + elif self._script.utilities.isMathLayoutOnly(index): + result = self._generateMath(index) + result.extend([messages.MATH_ROOT_OF]) + else: + oldRole = self._getAlternativeRole(index) + self._overrideRole(oldRole, args) + result.extend(self.generate(index, role=oldRole)) + self._restoreRole(oldRole, args) + result.extend([messages.MATH_ROOT_OF]) + + if result: + result.extend(self.voice(SYSTEM, obj=obj, **args)) + + return result + + def _generateRootBase(self, obj, **args): + base = self._script.utilities.getMathRootBase(obj) + if not base: + return [] + + if self._script.utilities.isMathSquareRoot(obj) \ + or self._script.utilities.isMathToken(base) \ + or self._script.utilities.isMathLayoutOnly(base): + return self._generateMath(base) + + result = [self._generatePause(obj, **args)] + oldRole = self._getAlternativeRole(base) + self._overrideRole(oldRole, args) + result.extend(self.generate(base, role=oldRole)) + self._restoreRole(oldRole, args) + + return result + + def _generateRootEnd(self, obj, **args): + result = [messages.MATH_ROOT_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateScriptBase(self, obj, **args): + base = self._script.utilities.getMathScriptBase(obj) + if not base: + return [] + + return self._generateMath(base) + + def _generateScriptScript(self, obj, **args): + if self._script.utilities.isMathLayoutOnly(obj): + return self._generateMath(obj) + + oldRole = self._getAlternativeRole(obj) + self._overrideRole(oldRole, args) + result = self.generate(obj, role=oldRole) + self._restoreRole(oldRole, args) + + return result + + def _generateScriptSubscript(self, obj, **args): + subscript = self._script.utilities.getMathScriptSubscript(obj) + if not subscript: + return [] + + result = [messages.MATH_SUBSCRIPT] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generateScriptScript(subscript)) + + return result + + def _generateScriptSuperscript(self, obj, **args): + superscript = self._script.utilities.getMathScriptSuperscript(obj) + if not superscript: + return [] + + result = [messages.MATH_SUPERSCRIPT] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generateScriptScript(superscript)) + + return result + + def _generateScriptUnderscript(self, obj, **args): + underscript = self._script.utilities.getMathScriptUnderscript(obj) + if not underscript: + return [] + + result = [messages.MATH_UNDERSCRIPT] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generateScriptScript(underscript)) + + return result + + def _generateScriptOverscript(self, obj, **args): + overscript = self._script.utilities.getMathScriptOverscript(obj) + if not overscript: + return [] + + result = [messages.MATH_OVERSCRIPT] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generateScriptScript(overscript)) + + return result + + def _generateScriptPrescripts(self, obj, **args): + result = [] + prescripts = self._script.utilities.getMathPrescripts(obj) + for i, script in enumerate(prescripts): + if self._script.utilities.isNoneElement(script): + continue + if i % 2: + rv = [messages.MATH_PRE_SUPERSCRIPT] + else: + rv = [messages.MATH_PRE_SUBSCRIPT] + rv.extend(self.voice(SYSTEM, obj=obj, **args)) + rv.extend(self._generateScriptScript(script)) + result.append(rv) + + return result + + def _generateScriptPostscripts(self, obj, **args): + result = [] + postscripts = self._script.utilities.getMathPostscripts(obj) + for i, script in enumerate(postscripts): + if self._script.utilities.isNoneElement(script): + continue + if i % 2: + rv = [messages.MATH_SUPERSCRIPT] + else: + rv = [messages.MATH_SUBSCRIPT] + rv.extend(self.voice(SYSTEM, obj=obj, **args)) + rv.extend(self._generateScriptScript(script)) + result.append(rv) + + return result + + def _generateMathTableStart(self, obj, **args): + try: + table = obj.queryTable() + except Exception: + return [] + + nestingLevel = self._script.utilities.getMathNestingLevel(obj) + if nestingLevel > 0: + result = [messages.mathNestedTableSize(table.nRows, table.nColumns)] + else: + result = [messages.mathTableSize(table.nRows, table.nColumns)] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + def _generateMathTableRows(self, obj, **args): + result = [] + for row in AXObject.iter_children(obj): + oldRole = self._getAlternativeRole(row) + self._overrideRole(oldRole, args) + result.extend(self.generate(row, role=oldRole)) + self._restoreRole(oldRole, args) + + return result + + def _generateMathRow(self, obj, **args): + result = [] + + result.append(messages.TABLE_ROW % (AXObject.get_index_in_parent(obj) + 1)) + result.extend(self.voice(SYSTEM, obj=obj, **args)) + result.extend(self._generatePause(obj, **args)) + + for child in AXObject.iter_children(obj): + result.extend(self._generateMath(child)) + result.extend(self._generatePause(child, **args)) + + return result + + def _generateMathTableEnd(self, obj, **args): + nestingLevel = self._script.utilities.getMathNestingLevel(obj) + if nestingLevel > 0: + result = [messages.MATH_NESTED_TABLE_END] + else: + result = [messages.MATH_TABLE_END] + result.extend(self.voice(SYSTEM, obj=obj, **args)) + return result + + ##################################################################### + # # + # Other things for prosody and voice selection # + # # + ##################################################################### + + def _generatePause(self, obj, **args): + if not _settingsManager.getSetting('enablePauseBreaks') \ + or args.get('eliminatePauses', False): + return [] + + if _settingsManager.getSetting('verbalizePunctuationStyle') == \ + settings.PUNCTUATION_STYLE_ALL: + return [] + + return PAUSE + + def _generateLineBreak(self, obj, **args): + return LINE_BREAK + + def voice(self, key=None, **args): + """Returns an array containing a voice. The key is a value + to be used to look up the voice in the settings.py:voices + dictionary. Other arguments can be passed in for future + decision making. + """ + + voicename = voiceType.get(key) or voiceType.get(DEFAULT) + voices = _settingsManager.getSetting('voices') + voice = acss.ACSS(voices.get(voiceType.get(DEFAULT), {})) + + language = args.get('language') + dialect = args.get('dialect', '') + msg = ( + f"SPEECH GENERATOR: {key} voice requested with " + f"language='{language}', dialect='{dialect}'" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + # This is purely for debugging. The code needed to actually switch voices + # does not yet exist due to some problems which need to be debugged and + # fixed. + checkVoicesForLanguage = False + if language and checkVoicesForLanguage: + server = speech.getSpeechServer() + server.shouldChangeVoiceForLanguage(language, dialect) + + if key in [None, DEFAULT]: + string = args.get('string', '') + obj = args.get('obj') + if AXUtilities.is_link(obj): + voice.update(voices.get(voiceType.get(HYPERLINK), {})) + elif isinstance(string, str) and string.isupper() and string.strip().isalpha(): + voice.update(voices.get(voiceType.get(UPPERCASE), {})) + else: + override = voices.get(voicename) + if override and override.get('established', True): + voice.update(override) + + return [voice] + + def utterancesToString(self, utterances): + string = "" + for u in utterances: + if isinstance(u, str): + string += f" {u}" + elif isinstance(u, Pause) and string and string[-1].isalnum(): + string += "." + + return string.strip() diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechdispatcherfactory.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechdispatcherfactory.py new file mode 100644 index 0000000..efb6297 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechdispatcherfactory.py @@ -0,0 +1,801 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides an Cthulhu speech server for Speech Dispatcher backend.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__author__ = "Tomas Cerha " +__copyright__ = "Copyright (c) 2006-2008 Brailcom, o.p.s." +__license__ = "LGPL" + +from gi.repository import GLib +import re +import time + +from . import chnames +from . import debug +from . import guilabels +from . import messages +from . import speechserver +from . import settings +from . import cthulhu_state +from . import punctuation_settings +from . import settings_manager +from .acss import ACSS + +_settingsManager = settings_manager.getManager() + +try: + import speechd +except Exception: + _speechd_available = False +else: + _speechd_available = True + try: + getattr(speechd, "CallbackType") + except AttributeError: + _speechd_version_ok = False + else: + _speechd_version_ok = True + +PUNCTUATION = re.compile(r'[^\w\s]', re.UNICODE) +ELLIPSIS = re.compile('(\342\200\246|(? debug.LEVEL_INFO: + return + + try: + sd_rate = self._send_command(self._client.get_rate) + sd_pitch = self._send_command(self._client.get_pitch) + sd_volume = self._send_command(self._client.get_volume) + sd_language = self._send_command(self._client.get_language) + except Exception: + sd_rate = sd_pitch = sd_volume = sd_language = "(exception occurred)" + + family = self._current_voice_properties.get(ACSS.FAMILY) + + styles = {settings.PUNCTUATION_STYLE_NONE: "NONE", + settings.PUNCTUATION_STYLE_SOME: "SOME", + settings.PUNCTUATION_STYLE_MOST: "MOST", + settings.PUNCTUATION_STYLE_ALL: "ALL"} + + msg = ( + f"SPEECH DISPATCHER: {prefix}\n" + f"CTHULHU rate {self._current_voice_properties.get(ACSS.RATE)}, " + f"pitch {self._current_voice_properties.get(ACSS.AVERAGE_PITCH)}, " + f"volume {self._current_voice_properties.get(ACSS.GAIN)}, " + f"language {self._get_language_and_dialect(family)[0]}, " + f"punctuation: " + f"{styles.get(_settingsManager.getSetting('verbalizePunctuationStyle'))}\n" + f"SD rate {sd_rate}, pitch {sd_pitch}, volume {sd_volume}, language {sd_language}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + def _apply_acss(self, acss): + if acss is None: + acss = settings.voices[settings.DEFAULT_VOICE] + current = self._current_voice_properties + for acss_property, method in self._acss_manipulators: + value = acss.get(acss_property) + if value is not None: + if current.get(acss_property) != value: + method(value) + current[acss_property] = value + elif acss_property == ACSS.AVERAGE_PITCH: + method(5.0) + current[acss_property] = 5.0 + elif acss_property == ACSS.GAIN: + method(10) + current[acss_property] = 5.0 + elif acss_property == ACSS.RATE: + method(50) + current[acss_property] = 5.0 + elif acss_property == ACSS.FAMILY: + method({}) + current[acss_property] = {} + + def __addVerbalizedPunctuation(self, oldText): + """Depending upon the users verbalized punctuation setting, + adjust punctuation symbols in the given text to their pronounced + equivalents. The pronounced text will either replace the + punctuation symbol or be inserted before it. In the latter case, + this is to retain spoken prosity. + + Arguments: + - oldText: text to be parsed for punctuation. + + Returns a text string with the punctuation symbols adjusted accordingly. + """ + + style = _settingsManager.getSetting("verbalizePunctuationStyle") + if style == settings.PUNCTUATION_STYLE_NONE: + return oldText + + spokenEllipsis = messages.SPOKEN_ELLIPSIS + " " + newText = re.sub(ELLIPSIS, spokenEllipsis, oldText) + symbols = set(re.findall(PUNCTUATION, newText)) + for symbol in symbols: + try: + level, action = punctuation_settings.getPunctuationInfo(symbol) + except Exception: + continue + + if level != punctuation_settings.LEVEL_NONE: + # Speech Dispatcher should handle it. + # + continue + + charName = f" {chnames.getCharacterName(symbol)} " + if action == punctuation_settings.PUNCTUATION_INSERT: + charName += symbol + newText = re.sub(symbol, charName, newText) + + if cthulhu_state.activeScript: + newText = cthulhu_state.activeScript.utilities.adjustForDigits(newText) + + return newText + + def _speak(self, text, acss, **kwargs): + if isinstance(text, ACSS): + text = '' + + # Mark beginning of words with U+E000 (private use) and record the + # string offsets + # Note: we need to do this before disturbing the text offsets + # Note2: we assume that text mangling below leave U+E000 untouched + last_begin = None + is_numeric = None + marks_offsets = [] + marks_endoffsets = [] + marked_text = "" + + for i in range(len(text)): + c = text[i] + if c == '\ue000': + # Original text already contains U+E000. But syntheses will not + # know what to do of it anyway, so discard it + continue + + if not c.isspace() and last_begin is None: + # Word begin + marked_text += '\ue000' + last_begin = i + is_numeric = c.isnumeric() + + elif c.isspace() and last_begin is not None: + # Word end + if is_numeric: + # We had a wholy numeric word, possibly next word is as well. + # Skip to next word + for j in range(i+1, len(text)): + if not text[j].isspace(): + break + else: + is_numeric = False + # Check next word + while is_numeric and j < len(text) and not text[j].isspace(): + if not text[j].isnumeric(): + is_numeric = False + j += 1 + + if not is_numeric: + # add a mark + marks_offsets.append(last_begin) + marks_endoffsets.append(i) + last_begin = None + is_numeric = None + + elif is_numeric and not c.isnumeric(): + is_numeric = False + + marked_text += c + + if last_begin is not None: + # Finished with a word + marks_offsets.append(last_begin) + marks_endoffsets.append(i + 1) + + text = marked_text + + text = self.__addVerbalizedPunctuation(text) + if cthulhu_state.activeScript: + text = cthulhu_state.activeScript.\ + utilities.adjustForPronunciation(text) + + # Replace no break space characters with plain spaces since some + # synthesizers cannot handle them. See bug #591734. + # + text = text.replace('\u00a0', ' ') + + # Replace newline followed by full stop, since + # this seems to crash sd, see bgo#618334. + # + text = text.replace('\n.', '\n') + + # Transcribe to SSML, translating U+E000 into marks + # Note: we need to do this after all mangling otherwise the ssml markup + # would get mangled too + ssml = "" + i = 0 + for c in text: + if c == '\ue000': + if i >= len(marks_offsets): + # This is really not supposed to happen + msg = f"{i}th U+E000 does not have corresponding index" + debug.printMessage(debug.LEVEL_WARNING, msg, True) + else: + ssml += '' % (marks_offsets[i], marks_endoffsets[i]) + i += 1 + # Disable for now, until speech dispatcher properly parses them (version 0.8.9 or later) + #elif c == '"': + # ssml += '"' + #elif c == "'": + # ssml += ''' + elif c == '<': + ssml += '<' + elif c == '>': + ssml += '>' + elif c == '&': + ssml += '&' + else: + ssml += c + ssml += "" + + self._apply_acss(acss) + self._debug_sd_values(f"Speaking '{ssml}' ") + self._send_command(self._client.speak, ssml, **kwargs) + + def _say_all(self, iterator, cthulhu_callback): + """Process another sayAll chunk. + + Called by the gidle thread. + + """ + try: + context, acss = next(iterator) + except StopIteration: + pass + else: + def callback(callbackType, index_mark=None): + # This callback is called in Speech Dispatcher listener thread. + # No subsequent Speech Dispatcher interaction is allowed here, + # so we pass the calls to the gidle thread. + t = self._CALLBACK_TYPE_MAP[callbackType] + if t == speechserver.SayAllContext.PROGRESS: + if index_mark: + index = index_mark.split(':') + if len(index) >= 2: + start, end = index[0:2] + context.currentOffset = context.startOffset + int(start) + context.currentEndOffset = context.startOffset + int(end) + msg = ( + f"SPEECH DISPATCHER: Got mark " + f"{context.currentOffset}:{context.currentEndOffset} / " + f"{context.startOffset}:{context.endOffset}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + else: + context.currentOffset = context.startOffset + context.currentEndOffset = None + elif t == speechserver.SayAllContext.COMPLETED: + context.currentOffset = context.endOffset + context.currentEndOffset = None + GLib.idle_add(cthulhu_callback, context.copy(), t) + if t == speechserver.SayAllContext.COMPLETED: + GLib.idle_add(self._say_all, iterator, cthulhu_callback) + self._speak(context.utterance, acss, callback=callback, + event_types=list(self._CALLBACK_TYPE_MAP.keys())) + return False # to indicate, that we don't want to be called again. + + def _cancel(self): + self._send_command(self._client.cancel) + + def _change_default_speech_rate(self, step, decrease=False): + acss = settings.voices[settings.DEFAULT_VOICE] + delta = step * (decrease and -1 or +1) + try: + rate = acss[ACSS.RATE] + except KeyError: + rate = 50 + acss[ACSS.RATE] = max(0, min(99, rate + delta)) + msg = f"SPEECH DISPATCHER: Rate set to {rate}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.speak(decrease and messages.SPEECH_SLOWER \ + or messages.SPEECH_FASTER, acss=acss) + + def _change_default_speech_pitch(self, step, decrease=False): + acss = settings.voices[settings.DEFAULT_VOICE] + delta = step * (decrease and -1 or +1) + try: + pitch = acss[ACSS.AVERAGE_PITCH] + except KeyError: + pitch = 5 + acss[ACSS.AVERAGE_PITCH] = max(0, min(9, pitch + delta)) + msg = f"SPEECH DISPATCHER: Pitch set to {pitch}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.speak(decrease and messages.SPEECH_LOWER \ + or messages.SPEECH_HIGHER, acss=acss) + + def _change_default_speech_volume(self, step, decrease=False): + acss = settings.voices[settings.DEFAULT_VOICE] + delta = step * (decrease and -1 or +1) + try: + volume = acss[ACSS.GAIN] + except KeyError: + volume = 10 + acss[ACSS.GAIN] = max(0, min(9, volume + delta)) + msg = f"SPEECH DISPATCHER: Volume set to {volume}" + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.speak(decrease and messages.SPEECH_SOFTER \ + or messages.SPEECH_LOUDER, acss=acss) + + def getInfo(self): + return [self._SERVER_NAMES.get(self._id, self._id), self._id] + + def getVoiceFamilies(self): + # Always offer the configured default voice with a language + # set according to the current locale. + from locale import getlocale, LC_MESSAGES + locale = getlocale(LC_MESSAGES)[0] + if locale is None or '_' not in locale: + locale_language = None + else: + locale_lang, locale_dialect = locale.split('_') + locale_language = locale_lang + '-' + locale_dialect + voices = () + try: + # This command is not available with older SD versions. + list_synthesis_voices = self._client.list_synthesis_voices + except AttributeError: + pass + else: + try: + voices += self._send_command(list_synthesis_voices) + except Exception: + pass + + default_lang = "" + if locale_language: + # Check whether how it appears in the server list + for name, lang, variant in voices: + if lang == locale_language: + default_lang = locale_language + break + if not default_lang: + for name, lang, variant in voices: + if lang == locale_lang: + default_lang = locale_lang + if not default_lang: + default_lang = locale_language + + voices = ((self._default_voice_name, default_lang, None),) + voices + + families = [] + for name, lang, variant in voices: + + families.append(speechserver.VoiceFamily({ \ + speechserver.VoiceFamily.NAME: name, + #speechserver.VoiceFamily.GENDER: speechserver.VoiceFamily.MALE, + speechserver.VoiceFamily.LANG: lang.partition("-")[0], + speechserver.VoiceFamily.DIALECT: lang.partition("-")[2], + speechserver.VoiceFamily.VARIANT: variant})) + + return families + + def speak(self, text=None, acss=None, interrupt=True): + if not text: + return + + # In order to re-enable this, a potentially non-trivial amount of work + # will be needed to ensure multiple utterances sent to speech.speak + # do not result in the intial utterances getting cut off before they + # can be heard by the user. Anyone needing to interrupt speech can + # do so via speech.stop -- or better yet, by using the default script + # method's presentationInterrupt. + #if interrupt: + # self._cancel() + + # "We will not interrupt a key echo in progress." (Said the comment in + # speech.py where these next two lines used to live. But the code here + # suggests we haven't been doing anything with the lastKeyEchoTime in + # years. TODO - JD: Dig into this and if it's truly useless, kill it.) + if self._lastKeyEchoTime: + interrupt = interrupt and (time.time() - self._lastKeyEchoTime) > 0.5 + + if len(text) == 1: + tokens = ["SPEECH DISPATCHER: Speaking '", text.replace("\n", "\\n"), "' as char"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._apply_acss(acss) + self._send_command(self._client.char, text) + else: + tokens = ["SPEECH DISPATCHER: Speaking '", text, "' as string"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._speak(text, acss) + + def sayAll(self, utteranceIterator, progressCallback): + GLib.idle_add(self._say_all, utteranceIterator, progressCallback) + + def speakCharacter(self, character, acss=None): + self._apply_acss(acss) + name = chnames.getCharacterName(character) + if not name or name == character: + tokens = ["SPEECH DISPATCHER: Speaking '", character.replace("\n", "\\n"), "' as char"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._send_command(self._client.char, character) + return + + if cthulhu_state.activeScript: + name = cthulhu_state.activeScript.\ + utilities.adjustForPronunciation(name) + self.speak(name, acss) + + def speakKeyEvent(self, event, acss=None): + event_string = event.getKeyName() + lockingStateString = event.getLockingStateString() + event_string = f"{event_string} {lockingStateString}".strip() + if len(event_string) == 1: + tokens = ["SPEECH DISPATCHER: Speaking '", event_string, "' as key"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self._apply_acss(acss) + self._send_command(self._client.key, event_string) + else: + tokens = ["SPEECH DISPATCHER: Speaking '", event_string, "' as string"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + self.speak(event_string, acss=acss) + self._lastKeyEchoTime = time.time() + + def increaseSpeechRate(self, step=5): + self._change_default_speech_rate(step) + + def decreaseSpeechRate(self, step=5): + self._change_default_speech_rate(step, decrease=True) + + def increaseSpeechPitch(self, step=0.5): + self._change_default_speech_pitch(step) + + def decreaseSpeechPitch(self, step=0.5): + self._change_default_speech_pitch(step, decrease=True) + + def increaseSpeechVolume(self, step=0.5): + self._change_default_speech_volume(step) + + def decreaseSpeechVolume(self, step=0.5): + self._change_default_speech_volume(step, decrease=True) + + def getLanguage(self): + """Returns the current language.""" + + return self._client.get_language() + + def setLanguage(self, language, dialect): + """Sets the current language""" + + if not language: + return + + self._client.set_language(language) + if dialect: + self._client.set_language(language + "-" + dialect) + + def _normalizedLanguageAndDialect(self, language, dialect=""): + """Attempts to ensure consistency across inconsistent formats.""" + + if "-" in language: + normalized_language = language.split("-", 1)[0].lower() + normalized_dialect = language.split("-", 1)[-1].lower() + else: + normalized_language = language.lower() + normalized_dialect = dialect.lower() + + return normalized_language, normalized_dialect + + def getVoiceFamiliesForLanguage(self, language, dialect, maximum=None): + """Returns the families for language available in the current synthesizer.""" + + start = time.time() + target_language, target_dialect = self._normalizedLanguageAndDialect(language, dialect) + + result = [] + voices = self._client.list_synthesis_voices() + + for voice in voices: + normalized_language, normalized_dialect = self._normalizedLanguageAndDialect(voice[1]) + if normalized_language != target_language: + continue + if normalized_dialect == target_dialect: + result.append(voice) + elif not normalized_dialect and target_dialect == normalized_language: + result.append(voice) + if maximum is not None and len(result) >= maximum: + break + + msg = ( + f"SPEECH DISPATCHER: Found {len(result)} match(es) for language='{language}' " + f"dialect='{dialect}' in {time.time() - start:.4f}s." + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + return result + + def shouldChangeVoiceForLanguage(self, language, dialect=""): + """Returns True if we should change the voice for the specified language.""" + + current_language, current_dialect = self._normalizedLanguageAndDialect(self.getLanguage()) + other_language, other_dialect = self._normalizedLanguageAndDialect(language, dialect) + + msg = ( + f"SPEECH DISPATCHER: Should change voice for language? " + f"Current: '{current_language}' '{current_dialect}' " + f"New: '{other_language}' '{other_dialect}'" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + + if current_language == other_language and current_dialect == other_dialect: + msg ="SPEECH DISPATCHER: No. Language and dialect are the same." + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + families = self.getVoiceFamiliesForLanguage(other_language, other_dialect, maximum=1) + if families: + tokens = ["SPEECH DISPATCHER: Yes. Found matching family", families[0], "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + tokens = ["SPEECH DISPATCHER: No. No matching family in", self.getOutputModule(), "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return True + + def getOutputModule(self): + return self._client.get_output_module() + + def setOutputModule(self, module): + self._client.set_output_module(module) + + def stop(self): + self._cancel() + + def shutdown(self): + self._client.close() + del SpeechServer._active_servers[self._id] + + def reset(self, text=None, acss=None): + self._client.close() + self._init() + + def list_output_modules(self): + """Return names of available output modules as a tuple of strings. + + This method is not a part of Cthulhu speech API, but is used internally + by the Speech Dispatcher backend. + + The returned tuple can be empty if the information can not be + obtained (e.g. with an older Speech Dispatcher version). + + """ + try: + return self._send_command(self._client.list_output_modules) + except AttributeError: + return () + except speechd.SSIPCommandError: + return () + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechserver.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechserver.py new file mode 100644 index 0000000..3901b67 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/speechserver.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides an abtract class for working with speech servers. + +A speech server (class SpeechServer) provides the ability to tell the +machine to speak. Each speech server provides a set of known +voices (identified by name) which can be combined with various +attributes to create aural style sheets.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." +__license__ = "LGPL" + +class VoiceFamily(dict): + """Holds the family description for a voice.""" + + NAME = "name" + GENDER = "gender" + LANG = "lang" + DIALECT = "dialect" + VARIANT = "variant" + + MALE = "male" + FEMALE = "female" + + settings = { + NAME : None, + GENDER : None, + LANG : None, + DIALECT: None, + VARIANT: None, + } + + def __init__(self, props): + """Create and initialize VoiceFamily.""" + dict.__init__(self) + + self.update(VoiceFamily.settings) + if props: + self.update(props) + +class SayAllContext: + + PROGRESS = 0 + INTERRUPTED = 1 + COMPLETED = 2 + + def __init__(self, obj, utterance, startOffset=-1, endOffset=-1): + """Creates a new SayAllContext that will be passed to the + SayAll callback handler for progress updates on speech. + If the object does not have an accessible text specialization, + then startOffset and endOffset parameters are meaningless. + If the object does have an accessible text specialization, + then values >= 0 for startOffset and endOffset indicate + where in the text the utterance has come from. + + Arguments: + -obj: the Accessible being spoken + -utterance: the actual utterance being spoken + -startOffset: the start offset of the Accessible's text + -endOffset: the end offset of the Accessible's text + """ + self.obj = obj + self.utterance = utterance + self.startOffset = startOffset + self.endOffset = endOffset + self.currentOffset = startOffset + self.currentEndOffset = None + + def __str__(self): + return "SAY ALL: %s '%s' (%i-%i, current: %i)" % \ + (self.obj, self.utterance, self.startOffset, self.endOffset, self.currentOffset) + + def copy(self): + new = SayAllContext(self.obj, self.utterance, + self.startOffset, self.endOffset) + new.currentOffset = self.currentOffset + new.currentEndOffset = self.currentEndOffset + return new + + def __eq__(self, other): + return (self.startOffset == other.startOffset and + self.endOffset == other.endOffset and + self.obj == other.obj and + self.utterance == other.utterance) + + +class SpeechServer(object): + """Provides speech server abstraction.""" + + @staticmethod + def getFactoryName(): + """Returns a localized name describing this factory.""" + pass + + @staticmethod + def getSpeechServers(): + """Gets available speech servers as a list. The caller + is responsible for calling the shutdown() method of each + speech server returned. + """ + pass + + @staticmethod + def getSpeechServer(info): + """Gets a given SpeechServer based upon the info. + See SpeechServer.getInfo() for more info. + """ + pass + + @staticmethod + def shutdownActiveServers(): + """Cleans up and shuts down this factory. + """ + pass + + def __init__(self): + pass + + def getInfo(self): + """Returns [name, id] + """ + pass + + def getVoiceFamilies(self): + """Returns a list of VoiceFamily instances representing all + voice families known by the speech server.""" + pass + + def speakCharacter(self, character, acss=None): + """Speaks a single character immediately. + + Arguments: + - character: text to be spoken + - acss: acss.ACSS instance; if None, + the default voice settings will be used. + Otherwise, the acss settings will be + used to augment/override the default + voice settings. + """ + pass + + def speakKeyEvent(self, event, acss=None): + """Speaks a key event immediately. + + Arguments: + - event: the input_event.KeyboardEvent. + """ + pass + + def speak(self, text=None, acss=None, interrupt=True): + """Speaks all queued text immediately. If text is not None, + it is added to the queue before speaking. + + Arguments: + - text: optional text to add to the queue before speaking + - acss: acss.ACSS instance; if None, + the default voice settings will be used. + Otherwise, the acss settings will be + used to augment/override the default + voice settings. + - interrupt: if True, stops any speech in progress before + speaking the text + """ + pass + + def sayAll(self, utteranceIterator, progressCallback): + """Iterates through the given utteranceIterator, speaking + each utterance one at a time. Subclasses may postpone + getting a new element until the current element has been + spoken. + + Arguments: + - utteranceIterator: iterator/generator whose next() function + returns a [SayAllContext, acss] tuple + - progressCallback: called as speech progress is made - has a + signature of (SayAllContext, type), where + type is one of PROGRESS, INTERRUPTED, or + COMPLETED. + """ + pass + + def increaseSpeechRate(self, step=5): + """Increases the speech rate. + """ + pass + + def decreaseSpeechRate(self, step=5): + """Decreases the speech rate. + """ + pass + + def increaseSpeechPitch(self, step=0.5): + """Increases the speech pitch. + """ + pass + + def decreaseSpeechPitch(self, step=0.5): + """Decreases the speech pitch. + """ + pass + + def updateCapitalizationStyle(self): + """Updates the capitalization style used by the speech server.""" + pass + + def updatePunctuationLevel(self): + """Punctuation level changed, inform this speechServer.""" + pass + + def stop(self): + """Stops ongoing speech and flushes the queue.""" + pass + + def shutdown(self): + """Shuts down the speech engine.""" + pass + + def reset(self, text=None, acss=None): + """Resets the speech engine.""" + pass diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/spellcheck.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/spellcheck.py new file mode 100644 index 0000000..348cb93 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/spellcheck.py @@ -0,0 +1,342 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Script-customizable support for application spellcheckers.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2014 Igalia, S.L." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +import re + +from cthulhu import debug +from cthulhu import guilabels +from cthulhu import messages +from cthulhu import object_properties +from cthulhu import cthulhu_state +from cthulhu import settings_manager +from cthulhu.ax_object import AXObject +from cthulhu.ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +class SpellCheck: + + def __init__(self, script, hasChangeToEntry=True): + self._script = script + self._hasChangeToEntry = hasChangeToEntry + self._window = None + self._errorWidget = None + self._changeToEntry = None + self._suggestionsList = None + self._activated = False + self._documentPosition = None, -1 + + self.spellErrorCheckButton = None + self.spellSuggestionCheckButton = None + self.presentContextCheckButton = None + + def activate(self, window): + tokens = ["SPELL CHECK: Attempting activation for", window] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + if not self._isCandidateWindow(window): + tokens = ["SPELL CHECK:", window, "is not spellcheck window"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return False + + if self._hasChangeToEntry: + self._changeToEntry = self._findChangeToEntry(window) + if not self._changeToEntry: + msg = 'SPELL CHECK: Change-to entry not found' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + self._errorWidget = self._findErrorWidget(window) + if not self._errorWidget: + msg = 'SPELL CHECK: Error widget not found' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + self._suggestionsList = self._findSuggestionsList(window) + if not self._suggestionsList: + msg = 'SPELL CHECK: Suggestions list not found' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return False + + self._window = window + self._activated = True + msg = 'SPELL CHECK: Activation complete' + debug.printMessage(debug.LEVEL_INFO, msg, True) + return True + + def deactivate(self): + self._clearState() + + def getDocumentPosition(self): + return self._documentPosition + + def setDocumentPosition(self, obj, offset): + self._documentPosition = obj, offset + + def getErrorWidget(self): + return self._errorWidget + + def getMisspelledWord(self): + if not self._errorWidget: + return "" + + return self._script.utilities.displayedText(self._errorWidget) + + def getCompletionMessage(self): + if not self._errorWidget: + return "" + + return self._script.utilities.displayedText(self._errorWidget) + + def getChangeToEntry(self): + return self._changeToEntry + + def getSuggestionsList(self): + return self._suggestionsList + + def isActive(self): + return self._activated + + def isCheckWindow(self, window): + if window and window == self._window: + return True + + return self.activate(window) + + def isComplete(self): + return not AXUtilities.is_sensitive(self._changeToEntry) + + def isAutoFocusEvent(self, event): + return False + + def isSuggestionsItem(self, obj): + if not self._suggestionsList: + return False + + return obj and AXObject.get_parent(obj) == self._suggestionsList + + def presentContext(self): + if not self.isActive(): + return False + + obj, offset = self._documentPosition + if not (obj and offset >= 0): + return False + + try: + text = obj.queryText() + except Exception: + return False + + # This should work, but some toolkits are broken. + boundary = Atspi.TextBoundaryType.SENTENCE_START + string, start, end = text.getTextAtOffset(offset, boundary) + + if not string: + boundary = Atspi.TextBoundaryType.LINE_START + string, start, end = text.getTextAtOffset(offset, boundary) + sentences = re.split(r'(?:\.|\!|\?)', string) + word = self.getMisspelledWord() + if string.count(word) == 1: + match = list(filter(lambda x: x.count(word), sentences)) + string = match[0] + + if not string: + return False + + msg = messages.MISSPELLED_WORD_CONTEXT % string + voice = self._script.speechGenerator.voice(string=msg) + self._script.speakMessage(msg, voice=voice) + return True + + def presentCompletionMessage(self): + if not (self.isActive() and self.isComplete()): + return False + + self._script.clearBraille() + msg = self.getCompletionMessage() + voice = self._script.speechGenerator.voice(string=msg) + self._script.presentMessage(msg, voice=voice) + return True + + def presentErrorDetails(self, detailed=False): + if self.isComplete(): + return False + + if self.presentMistake(detailed): + self.presentSuggestion(detailed) + if detailed or _settingsManager.getSetting('spellcheckPresentContext'): + self.presentContext() + return True + + return False + + def presentMistake(self, detailed=False): + if not self.isActive(): + return False + + word = self.getMisspelledWord() + if not word: + return False + + msg = messages.MISSPELLED_WORD % word + voice = self._script.speechGenerator.voice(string=msg) + self._script.speakMessage(msg, voice=voice) + if detailed or _settingsManager.getSetting('spellcheckSpellError'): + self._script.spellCurrentItem(word) + + return True + + def presentSuggestion(self, detailed=False): + if not self._hasChangeToEntry: + return self.presentSuggestionListItem(detailed, includeLabel=True) + + if not self.isActive(): + return False + + entry = self._changeToEntry + if not entry: + return False + + label = self._script.utilities.displayedLabel(entry) or AXObject.get_name(entry) + string = self._script.utilities.substring(entry, 0, -1) + msg = f"{label} {string}" + voice = self._script.speechGenerator.voice(string=msg) + self._script.speakMessage(msg, voice=voice) + if detailed or _settingsManager.getSetting('spellcheckSpellSuggestion'): + self._script.spellCurrentItem(string) + + return True + + def presentSuggestionListItem(self, detailed=False, includeLabel=False): + if not self.isActive(): + return False + + suggestions = self._suggestionsList + if not suggestions: + return False + + items = self._script.utilities.selectedChildren(suggestions) + if not len(items) == 1: + return False + + if includeLabel: + label = self._script.utilities.displayedLabel(suggestions) \ + or AXObject.get_name(suggestions) + else: + label = "" + string = AXObject.get_name(items[0]) + + msg = f"{label} {string}" + voice = self._script.speechGenerator.voice(string=msg) + self._script.speakMessage(msg.strip(), voice=voice) + if detailed or _settingsManager.getSetting('spellcheckSpellSuggestion'): + self._script.spellCurrentItem(string) + + if _settingsManager.getSetting('enablePositionSpeaking') \ + and items[0] == cthulhu_state.locusOfFocus: + index, total = self._getSuggestionIndexAndPosition(items[0]) + msg = object_properties.GROUP_INDEX_SPEECH % {"index": index, "total": total} + self._script.speakMessage(msg) + + return True + + def _clearState(self): + self._window = None + self._errorWidget = None + self._changeToEntry = None + self._suggestionsList = None + self._activated = False + + def _isCandidateWindow(self, window): + return False + + def _findChangeToEntry(self, root): + return None + + def _findErrorWidget(self, root): + return None + + def _findSuggestionsList(self, root): + return None + + def _getSuggestionIndexAndPosition(self, suggestion): + return -1, -1 + + def getAppPreferencesGUI(self): + + from gi.repository import Gtk + + frame = Gtk.Frame() + label = Gtk.Label(label=f"{guilabels.SPELL_CHECK}") + label.set_use_markup(True) + frame.set_label_widget(label) + + alignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) + alignment.set_padding(0, 0, 12, 0) + frame.add(alignment) + + grid = Gtk.Grid() + alignment.add(grid) + + label = guilabels.SPELL_CHECK_SPELL_ERROR + value = _settingsManager.getSetting('spellcheckSpellError') + self.spellErrorCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self.spellErrorCheckButton.set_active(value) + grid.attach(self.spellErrorCheckButton, 0, 0, 1, 1) + + label = guilabels.SPELL_CHECK_SPELL_SUGGESTION + value = _settingsManager.getSetting('spellcheckSpellSuggestion') + self.spellSuggestionCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self.spellSuggestionCheckButton.set_active(value) + grid.attach(self.spellSuggestionCheckButton, 0, 1, 1, 1) + + label = guilabels.SPELL_CHECK_PRESENT_CONTEXT + value = _settingsManager.getSetting('spellcheckPresentContext') + self.presentContextCheckButton = Gtk.CheckButton.new_with_mnemonic(label) + self.presentContextCheckButton.set_active(value) + grid.attach(self.presentContextCheckButton, 0, 2, 1, 1) + + return frame + + def getPreferencesFromGUI(self): + """Returns a dictionary with the app-specific preferences.""" + + return { + 'spellcheckSpellError': self.spellErrorCheckButton.get_active(), + 'spellcheckSpellSuggestion': self.spellSuggestionCheckButton.get_active(), + 'spellcheckPresentContext': self.presentContextCheckButton.get_active() + } diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/structural_navigation.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/structural_navigation.py new file mode 100644 index 0000000..87f8582 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/structural_navigation.py @@ -0,0 +1,2424 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Implements structural navigation.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc." \ + "Copyright (c) 2010-2013 The Cthulhu Team" +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import cmdnames +from . import debug +from . import guilabels +from . import input_event +from . import keybindings +from . import messages +from . import object_properties +from . import cthulhu_gui_navlist +from . import cthulhu_state +from . import settings +from . import settings_manager +from .ax_collection import AXCollection +from .ax_event_synthesizer import AXEventSynthesizer +from .ax_object import AXObject +from .ax_selection import AXSelection +from .ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +########################################################################### +# # +# StructuralNavigationObject # +# # +########################################################################### + +class StructuralNavigationObject: + """Represents a document object which has identifiable characteristics + which can be used for the purpose of navigation to and among instances + of that object. These characteristics may be something as simple as a + role and/or a state of interest. Or they may be something more complex + such as character counts, text attributes, and other object attributes. + """ + def __init__(self, structuralNavigation, objType, bindings, predicate, + criteria, presentation, dialogData, getter): + """Creates a new structural navigation object. + + Arguments: + - structuralNavigation: the StructuralNavigation class associated + with this object. + - objType: the type (e.g. BLOCKQUOTE) associated with this object. + - bindings: a dictionary of all of the possible bindings for this + object. In the case of all but the "atLevel" bindings, each + binding takes the form of [keysymstring, modifiers, description]. + The goPreviousAtLevel and goNextAtLevel bindings are each a list + of bindings in that form. + - predicate: the method to use to verify if a given accessible + matches this structural navigation object. Used only when the + collection interface does not provide a way for us to specify + needed condition(s). + - criteria: a method which returns a MatchRule object which is used + to find all matching objects via AtspiCollection. + - presentation: the method which should be called after performing + the search for the structural navigation object. + - dialogData: the method which returns the title, column headers, + and row data which should be included in the "list of" dialog for + the structural navigation object. + - getter: The function which should be used instead of the criteria + and predicate. + """ + + self.structuralNavigation = structuralNavigation + self.objType = objType + self.bindings = bindings + self.predicate = predicate + self.criteria = criteria + self.present = presentation + self._dialogData = dialogData + self.getter = getter + + self.inputEventHandlers = {} + self.keyBindings = keybindings.KeyBindings() + self.functions = [] + self._setUpHandlersAndBindings() + + def _setUpHandlersAndBindings(self): + """Adds the inputEventHandlers and keyBindings for this object.""" + + # Set up the basic handlers. These are our traditional goPrevious + # and goNext functions. + # + previousBinding = self.bindings.get("previous") + if previousBinding: + [keysymstring, modifiers, description] = previousBinding + handlerName = f"{self.objType}GoPrevious" + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(self.goPrevious, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(self.goPrevious) + + nextBinding = self.bindings.get("next") + if nextBinding: + [keysymstring, modifiers, description] = nextBinding + handlerName = f"{self.objType}GoNext" + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(self.goNext, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(self.goNext) + + listBinding = self.bindings.get("list") + if listBinding: + [keysymstring, modifiers, description] = listBinding + handlerName = f"{self.objType}ShowList" + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(self.showList, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(self.showList) + + # Set up the "at level" handlers (e.g. to navigate among headings + # at the specified level). + # + previousAtLevel = self.bindings.get("previousAtLevel") or [] + for i, binding in enumerate(previousAtLevel): + level = i + 1 + handler = self.goPreviousAtLevelFactory(level) + handlerName = "%sGoPreviousLevel%dHandler" % (self.objType, level) + keysymstring, modifiers, description = binding + + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(handler, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(handler) + + nextAtLevel = self.bindings.get("nextAtLevel") or [] + for i, binding in enumerate(nextAtLevel): + level = i + 1 + handler = self.goNextAtLevelFactory(level) + handlerName = "%sGoNextLevel%dHandler" % (self.objType, level) + keysymstring, modifiers, description = binding + + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(handler, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(handler) + + listAtLevel = self.bindings.get("listAtLevel") or [] + for i, binding in enumerate(listAtLevel): + level = i + 1 + handler = self.showListAtLevelFactory(level) + handlerName = "%sShowListAtLevel%dHandler" % (self.objType, level) + keysymstring, modifiers, description = binding + + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(handler, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(handler) + + # Set up the "directional" handlers (e.g. for table cells. Live + # region support has a handler to go to the last live region, + # so we'll handle that here as well). + # + directions = {} + directions["Left"] = self.bindings.get("left") + directions["Right"] = self.bindings.get("right") + directions["Up"] = self.bindings.get("up") + directions["Down"] = self.bindings.get("down") + directions["First"] = self.bindings.get("first") + directions["Last"] = self.bindings.get("last") + directions["Start"] = self.bindings.get("start") + directions["End"] = self.bindings.get("end") + + for direction in directions: + binding = directions.get(direction) + if not binding: + continue + + handler = self.goDirectionFactory(direction) + handlerName = f"{self.objType}Go{direction}" + keysymstring, modifiers, description = binding + + self.inputEventHandlers[handlerName] = \ + input_event.InputEventHandler(handler, description) + + self.keyBindings.add( + keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + self.inputEventHandlers[handlerName])) + + self.functions.append(handler) + + def addHandlerAndBinding(self, binding, handlerName, function): + """Adds a custom inputEventHandler and keybinding to the object's + handlers and bindings. Right now this is unused, but here in + case a creator of a StructuralNavigationObject had some other + desired functionality in mind. + + Arguments: + - binding: [keysymstring, modifiers, description] + - handlerName: a string uniquely identifying the handler + - function: the function associated with the binding + """ + + [keysymstring, modifiers, description] = binding + handler = input_event.InputEventHandler(function, description) + keyBinding = keybindings.KeyBinding( + keysymstring, + keybindings.defaultModifierMask, + modifiers, + handler) + + self.inputEventHandlers[handlerName] = handler + self.structuralNavigation.inputEventHandlers[handlerName] = handler + + self.functions.append(function) + self.structuralNavigation.functions.append(function) + + self.keyBindings.add(keyBinding) + self.structuralNavigation.keyBindings.add(keyBinding) + + def goPrevious(self, script, inputEvent): + """Go to the previous object.""" + self.structuralNavigation.goObject(self, False) + + def goNext(self, script, inputEvent): + """Go to the next object.""" + self.structuralNavigation.goObject(self, True) + + def showList(self, script, inputEvent): + """Show a list of all the items with this object type.""" + + objects = self.structuralNavigation._getAll(self) + + def _isValidMatch(x): + if AXObject.is_dead(x): + return False + return not (script.utilities.isHidden(x) or script.utilities.isEmpty(x)) + + objects = list(filter(_isValidMatch, objects)) + + if self.predicate is not None: + objects = list(filter(self.predicate, objects)) + + if self._dialogData is None: + msg = "STRUCTURAL NAVIGATION: Cannot show list without dialog data" + debug.printMessage(debug.LEVEL_INFO, msg, True) + return + + title, columnHeaders, rowData = self._dialogData() + count = len(objects) + title = f"{title}: {messages.itemsFound(count)}" + if not count: + script.presentMessage(title) + return + + currentObject, offset = script.utilities.getCaretContext() + try: + index = objects.index(currentObject) + except Exception: + index = 0 + + rows = [[obj, -1] + rowData(obj) for obj in objects] + cthulhu_gui_navlist.showUI(title, columnHeaders, rows, index) + + def goPreviousAtLevelFactory(self, level): + """Generates a goPrevious method for the specified level. Right + now, this is just for headings, but it may have applicability + for other objects such as list items (i.e. for level-based + navigation in an outline or other multi-tiered list. + + Arguments: + - level: the desired level of the object as an int. + """ + + def goPreviousAtLevel(script, inputEvent): + self.structuralNavigation.goObject(self, False, arg=level) + return goPreviousAtLevel + + def goNextAtLevelFactory(self, level): + """Generates a goNext method for the specified level. Right + now, this is just for headings, but it may have applicability + for other objects such as list items (i.e. for level-based + navigation in an outline or other multi-tiered list. + + Arguments: + - level: the desired level of the object as an int. + + """ + + def goNextAtLevel(script, inputEvent): + self.structuralNavigation.goObject(self, True, arg=level) + return goNextAtLevel + + def showListAtLevelFactory(self, level): + """Generates a showList method for the specified level. Right + now, this is just for headings, but it may have applicability + for other objects such as list items (i.e. for level-based + navigation in an outline or other multi-tiered list. + + Arguments: + - level: the desired level of the object as an int. + """ + + def showListAtLevel(script, inputEvent): + objects = self.structuralNavigation._getAll(self, arg=level) + + def _isValidMatch(x): + return not (script.utilities.isHidden(x) or script.utilities.isEmpty(x)) + + objects = list(filter(_isValidMatch, objects)) + if self.predicate is not None: + objects = list(filter(self.predicate, objects)) + + title, columnHeaders, rowData = self._dialogData(arg=level) + count = len(objects) + title = f"{title}: {messages.itemsFound(count)}" + if not count: + script.presentMessage(title) + return + + currentObject, offset = script.utilities.getCaretContext() + try: + index = objects.index(currentObject) + except Exception: + index = 0 + + rows = [[obj, -1] + rowData(obj) for obj in objects] + cthulhu_gui_navlist.showUI(title, columnHeaders, rows, index) + + return showListAtLevel + + def goDirectionFactory(self, direction): + """Generates the methods for navigation in a particular direction + (i.e. left, right, up, down, first, last). Right now, this is + primarily for table cells, but it may have applicability for other + objects. For example, when navigating in an outline, one might + want the ability to navigate to the next item at a given level, + but then work his/her way up/down in the hierarchy. + + Arguments: + - direction: the direction in which to navigate as a string. + """ + + def goCell(script, inputEvent): + obj, offset = script.utilities.getCaretContext() + thisCell = self.structuralNavigation.getCellForObj(obj) + currentCoordinates = self.structuralNavigation.getCellCoordinates(thisCell, False) + if direction == "Left": + desiredCoordinates = [currentCoordinates[0], + currentCoordinates[1] - 1] + elif direction == "Right": + desiredCoordinates = [currentCoordinates[0], + currentCoordinates[1] + 1] + elif direction == "Up": + desiredCoordinates = [currentCoordinates[0] - 1, + currentCoordinates[1]] + elif direction == "Down": + desiredCoordinates = [currentCoordinates[0] + 1, + currentCoordinates[1]] + elif direction == "First": + desiredCoordinates = [0, 0] + else: + desiredCoordinates = [-1, -1] + table = self.structuralNavigation.getTableForCell(thisCell) + if table: + nRows, nColumns = script.utilities.rowAndColumnCount(table, False) + lastRow = nRows - 1 + lastCol = nColumns - 1 + desiredCoordinates = [lastRow, lastCol] + self.structuralNavigation.goCell(self, + thisCell, + currentCoordinates, + desiredCoordinates) + + def goLastLiveRegion(script, inputEvent): + """Go to the last liveRegion.""" + if settings.inferLiveRegions: + script.liveRegionManager.goLastLiveRegion() + else: + script.presentMessage(messages.LIVE_REGIONS_OFF) + + def goContainerEdge(script, inputEvent): + isStart = direction == "Start" + self.structuralNavigation.goEdge(self, isStart) + + if self.objType == StructuralNavigation.CONTAINER: + return goContainerEdge + if self.objType == StructuralNavigation.TABLE_CELL: + return goCell + elif self.objType == StructuralNavigation.LIVE_REGION \ + and direction == "Last": + return goLastLiveRegion + +############################################################################# +# # +# StructuralNavigation # +# # +############################################################################# + +class StructuralNavigation: + """This class implements the structural navigation functionality which + is available to scripts. Scripts interested in implementing structural + navigation need to override getEnabledStructuralNavigationTypes() and + return a list of StructuralNavigation object types which should be + enabled. + """ + + # The available object types. + # + # Convenience methods have been put into place whereby one can + # create an object (FOO = "foo"), and then provide the following + # methods: _fooBindings(), _fooPredicate(), _fooCriteria(), and + # _fooPresentation(). With these in place, and with the object + # FOO included among the object types returned by the script's + # getEnabledStructuralNavigationTypes(), the StructuralNavigation + # object should be created and set up automagically. At least that + # is the idea. :-) This hopefully will also enable easy re-definition + # of existing StructuralNavigationObjects on a script-by-script basis. + # For instance, in the soffice script, overriding _blockquotePredicate + # should be all that is needed to implement navigation by blockquote + # in OOo Writer documents. + # + BLOCKQUOTE = "blockquote" + BUTTON = "button" + CHECK_BOX = "checkBox" + CHUNK = "chunk" + CLICKABLE = "clickable" + COMBO_BOX = "comboBox" + CONTAINER = "container" + ENTRY = "entry" + FORM_FIELD = "formField" + HEADING = "heading" + IMAGE = "image" + IFRAME = "iframe" + LANDMARK = "landmark" + LINK = "link" + LIST = "list" # Bulleted/numbered lists + LIST_ITEM = "listItem" # Bulleted/numbered list items + LIVE_REGION = "liveRegion" + PARAGRAPH = "paragraph" + RADIO_BUTTON = "radioButton" + SEPARATOR = "separator" + TABLE = "table" + TABLE_CELL = "tableCell" + UNVISITED_LINK = "unvisitedLink" + VISITED_LINK = "visitedLink" + + # Roles which are recognized as being potential "large objects" + # or "chunks." Note that this refers to AT-SPI roles. + # + OBJECT_ROLES = [Atspi.Role.HEADING, + Atspi.Role.LIST_ITEM, + Atspi.Role.MATH, + Atspi.Role.PARAGRAPH, + Atspi.Role.STATIC, + Atspi.Role.COLUMN_HEADER, + Atspi.Role.ROW_HEADER, + Atspi.Role.TABLE_CELL, + Atspi.Role.TABLE_ROW, + Atspi.Role.TEXT, + Atspi.Role.SECTION, + Atspi.Role.ARTICLE, + Atspi.Role.DESCRIPTION_TERM, + Atspi.Role.DESCRIPTION_VALUE, + Atspi.Role.DOCUMENT_EMAIL, + Atspi.Role.DOCUMENT_FRAME, + Atspi.Role.DOCUMENT_PRESENTATION, + Atspi.Role.DOCUMENT_SPREADSHEET, + Atspi.Role.DOCUMENT_TEXT, + Atspi.Role.DOCUMENT_WEB] + + CONTAINER_ROLES = [Atspi.Role.BLOCK_QUOTE, + Atspi.Role.DESCRIPTION_LIST, + Atspi.Role.FORM, + Atspi.Role.FOOTER, + Atspi.Role.HEADER, + Atspi.Role.LANDMARK, + Atspi.Role.LOG, + Atspi.Role.LIST, + Atspi.Role.MARQUEE, + Atspi.Role.PANEL, + Atspi.Role.SECTION, + Atspi.Role.TABLE, + Atspi.Role.TREE, + Atspi.Role.TREE_TABLE] + + def __init__(self, script, enabledTypes, enabled=False): + """Creates an instance of the StructuralNavigation class. + + Arguments: + - script: the script which which this instance is associated. + - enabledTypes: a list of StructuralNavigation object types + which the script is interested in supporting. + - enabled: Whether structural navigation should start out + enabled. For instance, in Gecko by default we do what it + enabled; in soffice, we would want to start out with it + disabled and have the user enable it via a keystroke when + desired. + """ + + self._script = script + self.enabled = enabled + + # Create all of the StructuralNavigationObject's in which the + # script is interested, using the convenience method + # + self.enabledObjects = {} + for objType in enabledTypes: + self.enabledObjects[objType] = \ + self.structuralNavigationObjectCreator(objType) + + self.functions = [] + self.inputEventHandlers = {} + self.setupInputEventHandlers() + self.keyBindings = self.getKeyBindings() + + # When navigating in a non-uniform table, one can move to a + # cell which spans multiple rows and/or columns. When moving + # beyond that cell, into a cell that does NOT span multiple + # rows/columns, we want to be sure we land in the right place. + # Therefore, we'll store the coordinates from "our perspective." + # + self.lastTableCell = [-1, -1] + + self._objectCache = {} + + self._inModalDialog = False + + def clearCache(self, document=None): + if document: + self._objectCache[hash(document)] = {} + else: + self._objectCache = {} + + def structuralNavigationObjectCreator(self, name): + """This convenience method creates a StructuralNavigationObject + with the specified name and associated characteristics. (See the + "Objects" section of code near the end of this class. Creators + of StructuralNavigationObject's can still do things the old + fashioned way should they so choose, by creating the instance + and then adding it via addObject(). + + Arguments: + - name: the name/objType associated with this object. + """ + + # Bindings and presentation are mandatory. + bindings = eval(f"self._{name}Bindings()") + presentation = eval(f"self._{name}Presentation") + + # Predicates should be the exception; not the rule. + try: + predicate = eval(f"self._{name}Predicate") + except Exception: + predicate = None + + # Dialogs are nice, but we shouldn't insist upon them. + try: + dialogData = eval(f"self._{name}DialogData") + except Exception: + dialogData = None + + # Criteria is the present, but being phased out. + try: + criteria = eval(f"self._{name}Criteria") + except Exception: + criteria = None + + # Getters are the future! + try: + getter = eval(f"self._{name}Getter") + except Exception: + getter = None + + return StructuralNavigationObject(self, name, bindings, predicate, + criteria, presentation, dialogData, getter) + + def addObject(self, objType, structuralNavigationObject): + """Adds structuralNavigationObject to the dictionary of enabled + objects. + + Arguments: + - objType: the name/object type of the StructuralNavigationObject. + - structuralNavigationObject: the StructuralNavigationObject to + add. + """ + + self.enabledObjects[objType] = structuralNavigationObject + + def setupInputEventHandlers(self): + """Defines InputEventHandler fields for a script.""" + + if not len(self.enabledObjects): + return + + self.inputEventHandlers["toggleStructuralNavigationHandler"] = \ + input_event.InputEventHandler( + self.toggleStructuralNavigation, + cmdnames.STRUCTURAL_NAVIGATION_TOGGLE) + + for structuralNavigationObject in self.enabledObjects.values(): + self.inputEventHandlers.update(\ + structuralNavigationObject.inputEventHandlers) + self.functions.extend(structuralNavigationObject.functions) + + def getKeyBindings(self): + """Defines the structural navigation key bindings for a script. + + Returns: an instance of keybindings.KeyBindings. + """ + + keyBindings = keybindings.KeyBindings() + + if not len(self.enabledObjects): + return keyBindings + + keyBindings.add( + keybindings.KeyBinding( + "z", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self.inputEventHandlers["toggleStructuralNavigationHandler"])) + + for structuralNavigationObject in self.enabledObjects.values(): + bindings = structuralNavigationObject.keyBindings.keyBindings + for keybinding in bindings: + keyBindings.add(keybinding) + + return keyBindings + + ######################################################################### + # # + # Input Event Handler Methods # + # # + ######################################################################### + + def toggleStructuralNavigation(self, script, inputEvent, presentMessage=True): + """Toggles structural navigation keys.""" + + self.enabled = not self.enabled + + if self.enabled: + string = messages.STRUCTURAL_NAVIGATION_KEYS_ON + else: + string = messages.STRUCTURAL_NAVIGATION_KEYS_OFF + + if presentMessage: + self._script.presentMessage(string) + + ######################################################################### + # # + # Methods for Moving to Objects # + # # + ######################################################################### + + def goCell(self, structuralNavigationObject, thisCell, + currentCoordinates, desiredCoordinates): + """The method used for navigation among cells in a table. + + Arguments: + - structuralNavigationObject: the StructuralNavigationObject which + represents the table cell. + - thisCell: the accessible TABLE_CELL we're currently in + - currentCoordinates: the [row, column] of thisCell. Note, we + cannot just get the coordinates because in table cells which + span multiple rows and/or columns, the value returned by + table.getRowAtIndex() is the first row the cell spans. Likewise, + the value returned by table.getColumnAtIndex() is the left-most + column. Therefore, we keep track of the row and column from + our perspective to ensure we stay in the correct row and column. + - desiredCoordinates: the [row, column] where we think we'd like to + be. + """ + + table = self.getTableForCell(thisCell) + if not table: + self._script.presentMessage(messages.TABLE_NOT_IN_A) + return None + + currentRow, currentCol = currentCoordinates + desiredRow, desiredCol = desiredCoordinates + rowDiff = desiredRow - currentRow + colDiff = desiredCol - currentCol + + nRows, nColumns = self._script.utilities.rowAndColumnCount(table, False) + cell = thisCell + while cell: + cell = self._script.utilities.cellForCoordinates(table, desiredRow, desiredCol) + if not cell: + if desiredCol < 0: + self._script.presentMessage(messages.TABLE_ROW_BEGINNING) + desiredCol = 0 + elif desiredCol > nColumns - 1: + self._script.presentMessage(messages.TABLE_ROW_END) + desiredCol = nColumns - 1 + if desiredRow < 0: + self._script.presentMessage(messages.TABLE_COLUMN_TOP) + desiredRow = 0 + elif desiredRow > nRows - 1: + self._script.presentMessage(messages.TABLE_COLUMN_BOTTOM) + desiredRow = nRows - 1 + elif (thisCell == cell and (colDiff or rowDiff)) \ + or (settings.skipBlankCells and self._isBlankCell(cell)): + if colDiff < 0: + desiredCol -= 1 + elif colDiff > 0: + desiredCol += 1 + if rowDiff < 0: + desiredRow -= 1 + elif rowDiff > 0: + desiredRow += 1 + else: + break + + self.lastTableCell = [desiredRow, desiredCol] + if cell: + oldRowHeaders = self._script.utilities.rowHeadersForCell(thisCell) + oldColHeaders = self._script.utilities.columnHeadersForCell(thisCell) + arg = [rowDiff, colDiff, oldRowHeaders, oldColHeaders] + structuralNavigationObject.present(cell, arg) + + def _getAll(self, structuralNavigationObject, arg=None): + """Returns all the instances of structuralNavigationObject.""" + + modalDialog = self._script.utilities.getModalDialog(cthulhu_state.locusOfFocus) + inModalDialog = bool(modalDialog) + if self._inModalDialog != inModalDialog: + msg = ( + f"STRUCTURAL NAVIGATION: in modal dialog has changed from " + f"{self._inModalDialog} to {inModalDialog}" + ) + debug.printMessage(debug.LEVEL_INFO, msg, True) + self.clearCache() + self._inModalDialog = inModalDialog + + document = self._script.utilities.documentFrame() + cache = self._objectCache.get(hash(document), {}) + key = f"{structuralNavigationObject.objType}:{arg}" + matches = cache.get(key, []) + if matches: + tokens = ["STRUCTURAL NAVIGATION: Returning", len(matches), "matches from cache"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return matches.copy() + + if structuralNavigationObject.getter: + matches = structuralNavigationObject.getter(document, arg) + elif not structuralNavigationObject.criteria: + return [] + elif not AXObject.supports_collection(document): + tokens = ["STRUCTURAL NAVIGATION:", document, "does not support collection"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + else: + rule = structuralNavigationObject.criteria(arg) + matches = AXCollection.get_all_matches(document, rule) + + if inModalDialog: + originalSize = len(matches) + matches = [m for m in matches if AXObject.find_ancestor(m, lambda x: x == modalDialog)] + tokens = ["STRUCTURAL NAVIGATION: Removed", {originalSize - len(matches)}, + "objects outside of modal dialog", modalDialog] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + rv = matches.copy() + cache[key] = matches + self._objectCache[hash(document)] = cache + return rv + + def goEdge(self, structuralNavigationObject, isStart, container=None, arg=None): + if container is None: + obj, offset = self._script.utilities.getCaretContext() + container = self.getContainerForObject(obj) + + if container is None or AXObject.is_dead(container): + structuralNavigationObject.present(None, arg) + return + + if isStart: + obj, offset = self._script.utilities.nextContext(container, -1) + structuralNavigationObject.present(obj, offset) + return + + # Unlike going to the start of the container, when we move to the next edge + # we pass beyond it on purpose. This makes us consistent with NVDA. + obj, offset = self._script.utilities.lastContext(container) + newObj, newOffset = self._script.utilities.nextContext(obj, offset) + if not newObj: + document = self._script.utilities.getDocumentForObject(obj) + newObj = self._script.utilities.getNextObjectInDocument(obj, document) + + newContainer = self.getContainerForObject(newObj) + if newObj and newContainer != container: + structuralNavigationObject.present(newObj, newOffset) + return + + if obj == container: + obj = AXObject.get_child(obj, -1) + + structuralNavigationObject.present(obj, sameContainer=True) + + def goObject(self, structuralNavigationObject, isNext, obj=None, arg=None): + """The method used for navigation among StructuralNavigationObjects + which are not table cells. + + Arguments: + - structuralNavigationObject: the StructuralNavigationObject which + represents the object of interest. + - isNext: If True, we're interested in the next accessible object + which matches structuralNavigationObject. If False, we're + interested in the previous accessible object which matches. + - obj: the current object (typically the locusOfFocus). + - arg: optional arguments which may need to be passed along to + the predicate, presentation method, etc. For instance, in the + case of navigating amongst headings at a given level, the level + is needed and passed in as arg. + """ + + matches = self._getAll(structuralNavigationObject, arg) + if not matches: + structuralNavigationObject.present(None, arg) + return + + if not isNext: + matches.reverse() + + def _isValidMatch(obj): + if AXObject.is_dead(obj): + return False + if self._script.utilities.isHidden(obj) or self._script.utilities.isEmpty(obj): + return False + if structuralNavigationObject.predicate is None: + return True + return structuralNavigationObject.predicate(obj) + + def _getMatchingObjAndIndex(obj): + while obj: + if obj in matches: + return obj, matches.index(obj) + obj = AXObject.get_parent(obj) + + return None, -1 + + offset = 0 + if not obj: + obj, offset = self._script.utilities.getCaretContext() + thisObj, index = _getMatchingObjAndIndex(obj) + if thisObj: + matches = matches[index:] + obj = thisObj + + currentPath = AXObject.get_path(obj) + for i, match in enumerate(matches): + if not _isValidMatch(match): + continue + + if AXObject.get_parent(match) == obj: + comparison = self._script.utilities.characterOffsetInParent(match) - offset + else: + path = AXObject.get_path(match) + comparison = self._script.utilities.pathComparison(path, currentPath) + if (comparison > 0 and isNext) or (comparison < 0 and not isNext): + structuralNavigationObject.present(match, arg) + return + + if not settings.wrappedStructuralNavigation: + structuralNavigationObject.present(None, arg) + return + + if not isNext: + self._script.presentMessage(messages.WRAPPING_TO_BOTTOM) + else: + self._script.presentMessage(messages.WRAPPING_TO_TOP) + + matches = self._getAll(structuralNavigationObject, arg) + if not isNext: + matches.reverse() + + for match in matches: + if _isValidMatch(match): + structuralNavigationObject.present(match, arg) + return + + structuralNavigationObject.present(None, arg) + + ######################################################################### + # # + # Methods for Presenting Objects # + # # + ######################################################################### + + def _getListDescription(self, obj): + children = [x for x in AXObject.iter_children(obj, AXUtilities.is_list_item)] + if not children: + return "" + + return messages.listItemCount(len(children)) + + def _getTableCaption(self, obj): + """Returns a string which contains the table caption, or + None if a caption could not be found. + + Arguments: + - obj: the accessible table whose caption we want. + """ + + caption = obj.queryTable().caption + try: + caption.queryText() + except Exception: + return None + else: + return self._script.utilities.displayedText(caption) + + def _getTableDescription(self, obj): + """Returns a string which describes the table.""" + + nonUniformString = "" + nonUniform = self._script.utilities.isNonUniformTable(obj) + if nonUniform: + nonUniformString = messages.TABLE_NON_UNIFORM + " " + + nRows, nColumns = self._script.utilities.rowAndColumnCount(obj, True) + sizeString = messages.tableSize(nRows, nColumns) + return (nonUniformString + sizeString) + + def getCellForObj(self, obj): + """Looks for a table cell in the ancestry of obj, if obj is not a + table cell. + + Arguments: + - obj: the accessible object of interest. + """ + + if not AXUtilities.is_table_cell_or_header(obj): + obj = AXObject.find_ancestor(obj, AXUtilities.is_table_cell_or_header) + + while obj and self._script.utilities.isLayoutOnly(self.getTableForCell(obj)): + cell = AXObject.find_ancestor(obj, AXUtilities.is_table_cell_or_header) + if cell is None: + break + obj = cell + + return obj + + def _isContainer(self, obj): + role = AXObject.get_role(obj) + if role not in self.CONTAINER_ROLES: + return False + + if role == Atspi.Role.SECTION \ + and not self._script.utilities.isLandmark(obj) \ + and not self._script.utilities.isBlockquote(obj): + return False + + return self._script.utilities.inDocumentContent(obj) + + def getContainerForObject(self, obj): + if not obj: + return None + + if self._isContainer(obj): + return obj + + return AXObject.find_ancestor(obj, self._isContainer) + + def getTableForCell(self, obj): + """Looks for a table in the ancestry of obj, if obj is not a table. + + Arguments: + - obj: the accessible object of interest. + """ + + if obj and not AXUtilities.is_table(obj): + obj = AXObject.find_ancestor(obj, AXUtilities.is_table) + + return obj + + def _isBlankCell(self, obj): + """Returns True if the table cell is empty or consists of whitespace. + + Arguments: + - obj: the accessible table cell to examine + """ + + if obj and (AXObject.get_name(obj) or AXObject.get_child_count(obj)): + return False + + try: + text = obj.queryText() + except Exception: + pass + else: + if text.getText(0, -1).strip(): + return False + + return True + + def _getCellText(self, obj): + """Looks at the table cell and tries to get its text. + + Arguments: + - obj: the accessible table cell to examine + """ + + text = "" + if obj and not AXObject.get_child_count(obj): + text = self._script.utilities.displayedText(obj) + else: + for child in AXObject.iter_children(obj): + childText = self._script.utilities.displayedText(child) + text = self._script.utilities.appendString(text, childText) + + return text + + def _presentCellHeaders(self, cell, oldCellInfo): + """Speaks the headers of the accessible table cell, cell. + + Arguments: + - cell: the accessible table cell whose headers we wish to + present. + - oldCellInfo: [rowDiff, colDiff, oldRowHeaders, oldColHeaders] + """ + + if not cell or not oldCellInfo: + return + + rowDiff, colDiff, oldRowHeaders, oldColHeaders = oldCellInfo + if not (oldRowHeaders or oldColHeaders): + return + + if rowDiff: + rowHeaders = self._script.utilities.rowHeadersForCell(cell) + for header in rowHeaders: + if header not in oldRowHeaders: + text = self._getCellText(header) + voice = self._script.speechGenerator.voice(string=text) + self._script.speakMessage(text, voice=voice, force=True) + + if colDiff: + colHeaders = self._script.utilities.columnHeadersForCell(cell) + for header in colHeaders: + if header not in oldColHeaders: + text = self._getCellText(header) + voice = self._script.speechGenerator.voice(string=text) + self._script.speakMessage(text, voice=voice, force=True) + + def getCellCoordinates(self, obj, preferAttribute=True): + """Returns the [row, col] of a ROLE_TABLE_CELL or [-1, -1] + if the coordinates cannot be found. + + Arguments: + - obj: the accessible table cell whose coordinates we want. + - preferAttribute: If True, prefer object attribute over table interface + """ + + cell = self.getCellForObj(obj) + table = self.getTableForCell(cell) + thisRow, thisCol = self._script.utilities.coordinatesForCell(cell, preferAttribute) + + # If preferAttribute is True, we are getting coordinates to be spoken, + # and not to deal with the logic below. + if preferAttribute: + return thisRow, thisCol + + # If we're in a cell that spans multiple rows and/or columns, + # thisRow and thisCol will refer to the upper left cell in + # the spanned range(s). We're storing the lastTableCell that + # we're aware of in order to facilitate more linear movement. + # Therefore, if the lastTableCell and this table cell are the + # same cell, we'll go with the stored coordinates. + lastRow, lastCol = self.lastTableCell + lastCell = self._script.utilities.cellForCoordinates(table, lastRow, lastCol) + if lastCell == cell: + return lastRow, lastCol + + return thisRow, thisCol + + def _getCaretPosition(self, obj): + """Returns the [obj, characterOffset] where the caret should be + positioned. For most scripts, the object should not change and + the offset should be 0. That's not always the case with Gecko. + + Arguments: + - obj: the accessible object in which the caret should be + positioned. + """ + + return self._script.utilities.getFirstCaretPosition(obj) + + def _setCaretPosition(self, obj, characterOffset): + """Sets the caret at the specified offset within obj.""" + + objPath = AXObject.get_path(obj) + objRole = AXObject.get_role(obj) + if objRole == Atspi.Role.INVALID: + return obj, characterOffset + + self._script.utilities.setCaretPosition(obj, characterOffset) + AXObject.clear_cache(obj) + if not AXUtilities.is_defunct(obj): + return obj, characterOffset + + tokens = ["STRUCTURAL NAVIGATION:", obj, "became defunct after setting caret position"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + replicant = self._script.utilities.getObjectFromPath(objPath) + if replicant and AXObject.get_role(replicant) == objRole: + tokens = ["STRUCTURAL NAVIGATION: Updating obj to replicant", replicant] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + obj = replicant + + return obj, characterOffset + + def _presentLine(self, obj, offset): + """Presents the first line of the object to the user. + + Arguments: + - obj: the accessible object to be presented. + - offset: the character offset within obj. + """ + + if not obj: + return + + if self._presentWithSayAll(obj, offset): + return + + self._script.updateBraille(obj) + self._script.sayLine(obj) + + def _presentObject(self, obj, offset, priorObj=None): + """Presents the entire object to the user. + + Arguments: + - obj: the accessible object to be presented. + - offset: the character offset within obj. + """ + + if not obj: + return + + if self._presentWithSayAll(obj, offset): + return + + AXEventSynthesizer.scroll_to_top_edge(obj) + self._script.presentObject(obj, offset=offset, priorObj=priorObj, interrupt=True) + + def _presentWithSayAll(self, obj, offset): + if self._script.inSayAll() \ + and _settingsManager.getSetting('structNavInSayAll'): + self._script.sayAll(obj, offset) + return True + + return False + + def _getRoleName(self, obj): + # Another case where we'll do this for now, and clean it up when + # object presentation is refactored. + return self._script.speechGenerator.getLocalizedRoleName(obj) + + def _getSelectedItem(self, obj): + # Another case where we'll do this for now, and clean it up when + # object presentation is refactored. + if AXUtilities.is_combo_box(obj): + obj = AXObject.get_child(obj, 0) + + if not AXObject.supports_selection(obj): + return None + + return AXSelection.get_selected_child(obj, 0) + + def _getText(self, obj): + # Another case where we'll do this for now, and clean it up when + # object presentation is refactored. + text = self._script.utilities.displayedText(obj) + if not text: + text = self._script.utilities.expandEOCs(obj) + if not text: + item = self._getSelectedItem(obj) + if item: + text = AXObject.get_name(item) + if not text and AXUtilities.is_image(obj): + try: + image = obj.queryImage() + except Exception: + text = AXObject.get_description(obj) + else: + text = image.imageDescription or AXObject.get_description(obj) + if not text: + parent = AXObject.get_parent(obj) + if AXUtilities.is_link(parent): + text = self._script.utilities.linkBasename(parent) + if not text and AXUtilities.is_list(obj): + children = [x for x in AXObject.iter_children(obj, AXUtilities.is_list_item)] + text = " ".join(list(map(self._getText, children))) + + return text + + def _getLabel(self, obj): + # Another case where we'll do this for now, and clean it up when + # object presentation is refactored. + label = self._script.utilities.displayedLabel(obj) + if not label: + label, objects = self._script.labelInference.infer( + obj, focusedOnly=False) + + return label + + def _getState(self, obj): + # Another case where we'll do this for now, and clean it up when + # object presentation is refactored. + + # For now, we'll just grab the spoken indicator from settings. + # When object presentation is refactored, we can clean this up. + if AXUtilities.is_check_box(obj): + unchecked, checked, partially = object_properties.CHECK_BOX_INDICATORS_SPEECH + if AXUtilities.is_indeterminate(obj): + return partially + if AXUtilities.is_checked(obj): + return checked + return unchecked + + if AXUtilities.is_radio_button(obj): + unselected, selected = object_properties.RADIO_BUTTON_INDICATORS_SPEECH + if AXUtilities.is_checked(obj): + return selected + return unselected + + if AXUtilities.is_link(obj): + if AXUtilities.is_visited(obj): + return object_properties.STATE_VISITED + else: + return object_properties.STATE_UNVISITED + + return '' + + def _getValue(self, obj): + # Another case where we'll do this for now, and clean it up when + # object presentation is refactored. + return self._getState(obj) or self._getText(obj) + + ######################################################################### + # # + # Objects # + # # + ######################################################################### + + # All structural navigation objects have the following essential + # characteristics: + # + # 1. Keybindings for goPrevious, goNext, and other such methods. + # This is a dictionary. See _setUpHandlersAndBindings() for + # supported values. But "previous", "next", and "list" are + # typically what you'll need. + # 2. A means of identification: MatchCriteria and optional predicate. + # The MatchCriteria is required. For ATK implementations, AT-SPI2 + # implements Collection. Applications and toolkits which implement + # AT-SPI2 directly should provide the implementation because our + # getting all objects via a tree dive is extremely non-performant. + # The predicate is only needed if Collection lacks something we + # need to identify the object is really the thing we want. Usually + # the predicate is not needed and can remain undefined. + # 3. A definition of how the object should be presented (both when + # another instance of that object is found as well as when it is + # not). This function should do the presentation. + # 4. Details needed to populate the dialog with the object list is + # presented. + # + # Convenience methods have been put into place whereby one can + # create an object (FOO = "foo"), and then provide the following + # methods: _fooBindings(), _fooPredicate(), _fooCriteria(), and + # _fooPresentation(). With these in place, and with the object + # FOO included among the StructuralNavigation.enabledTypes for + # the script, the structural navigation object should be created + # and set up automagically. At least that is the idea. :-) This + # hopefully will also enable easy re-definition of existing + # objects on a script-by-script basis. + + ######################## + # # + # Blockquotes # + # # + ######################## + + def _blockquoteBindings(self): + bindings = {} + prevDesc = cmdnames.BLOCKQUOTE_PREV + bindings["previous"] = ["q", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.BLOCKQUOTE_NEXT + bindings["next"] = ["q", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.BLOCKQUOTE_LIST + bindings["list"] = ["q", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _blockquoteGetter(self, document, arg=None): + return AXUtilities.find_all_block_quotes(document) + + def _blockquotePresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_BLOCKQUOTES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _blockquoteDialogData(self): + columnHeaders = [guilabels.SN_HEADER_BLOCKQUOTE] + + def rowData(obj): + return [self._getText(obj)] + + return guilabels.SN_TITLE_BLOCKQUOTE, columnHeaders, rowData + + ######################## + # # + # Buttons # + # # + ######################## + + def _buttonBindings(self): + bindings = {} + prevDesc = cmdnames.BUTTON_PREV + bindings["previous"] = ["b", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.BUTTON_NEXT + bindings["next"] = ["b", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.BUTTON_LIST + bindings["list"] = ["b", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _buttonGetter(self, document, arg=None): + return AXUtilities.find_all_buttons(document) + + def _buttonPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_BUTTONS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _buttonDialogData(self): + columnHeaders = [guilabels.SN_HEADER_BUTTON] + + def rowData(obj): + return [self._getText(obj)] + + return guilabels.SN_TITLE_BUTTON, columnHeaders, rowData + + ######################## + # # + # Check boxes # + # # + ######################## + + def _checkBoxBindings(self): + bindings = {} + prevDesc = cmdnames.CHECK_BOX_PREV + bindings["previous"] = ["x", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.CHECK_BOX_NEXT + bindings["next"] = ["x", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.CHECK_BOX_LIST + bindings["list"] = ["x", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _checkBoxGetter(self, document, arg=None): + return AXUtilities.find_all_check_boxes(document) + + def _checkBoxPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_CHECK_BOXES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _checkBoxDialogData(self): + columnHeaders = [guilabels.SN_HEADER_CHECK_BOX] + columnHeaders.append(guilabels.SN_HEADER_STATE) + + def rowData(obj): + return [self._getLabel(obj), self._getState(obj)] + + return guilabels.SN_TITLE_CHECK_BOX, columnHeaders, rowData + + ######################## + # # + # Chunks/Large Objects # + # # + ######################## + + def _chunkBindings(self): + bindings = {} + prevDesc = cmdnames.LARGE_OBJECT_PREV + bindings["previous"] = ["o", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.LARGE_OBJECT_NEXT + bindings["next"] = ["o", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.LARGE_OBJECT_LIST + bindings["list"] = ["o", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _chunkCriteria(self, arg=None): + return AXCollection.create_match_rule(roles=self.OBJECT_ROLES + self.CONTAINER_ROLES) + + def _chunkPredicate(self, obj, arg=None): + if AXUtilities.is_heading(obj): + return True + + text = self._script.utilities.queryNonEmptyText(obj) + if not (text and text.characterCount > settings.largeObjectTextLength): + return False + + string = text.getText(0, -1) + eocs = string.count(self._script.EMBEDDED_OBJECT_CHARACTER) + if eocs/text.characterCount < 0.05: + return True + + return False + + def _chunkPresentation(self, obj, arg=None): + if obj is not None: + [newObj, characterOffset] = self._getCaretPosition(obj) + self._setCaretPosition(newObj, characterOffset) + self._presentObject(obj, 0) + else: + full = messages.NO_MORE_CHUNKS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _chunkDialogData(self): + columnHeaders = [guilabels.SN_HEADER_OBJECT] + columnHeaders.append(guilabels.SN_HEADER_ROLE) + + def rowData(obj): + return [self._getText(obj), self._getRoleName(obj)] + + return guilabels.SN_TITLE_LARGE_OBJECT, columnHeaders, rowData + + ######################## + # # + # Combo Boxes # + # # + ######################## + + def _comboBoxBindings(self): + bindings = {} + prevDesc = cmdnames.COMBO_BOX_PREV + bindings["previous"] = ["c", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.COMBO_BOX_NEXT + bindings["next"] = ["c", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.COMBO_BOX_LIST + bindings["list"] = ["c", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _comboBoxGetter(self, document, arg=None): + return AXUtilities.find_all_combo_boxes(document) + + def _comboBoxPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_COMBO_BOXES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _comboBoxDialogData(self): + columnHeaders = [guilabels.SN_HEADER_COMBO_BOX] + columnHeaders.append(guilabels.SN_HEADER_SELECTED_ITEM) + + def rowData(obj): + return [self._getLabel(obj), self._getText(obj)] + + return guilabels.SN_TITLE_COMBO_BOX, columnHeaders, rowData + + ######################## + # # + # Entries # + # # + ######################## + + def _entryBindings(self): + bindings = {} + prevDesc = cmdnames.ENTRY_PREV + bindings["previous"] = ["e", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.ENTRY_NEXT + bindings["next"] = ["e", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.ENTRY_LIST + bindings["list"] = ["e", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _entryGetter(self, document, arg=None): + def parent_is_not_editable(obj): + parent = AXObject.get_parent(obj) + return parent is not None and not AXUtilities.is_editable(parent) + return AXUtilities.find_all_editable_objects(document, pred=parent_is_not_editable) + + def _entryPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_ENTRIES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _entryDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LABEL] + columnHeaders.append(guilabels.SN_HEADER_TEXT) + + def rowData(obj): + return [self._getLabel(obj), self._getText(obj)] + + return guilabels.SN_TITLE_ENTRY, columnHeaders, rowData + + ######################## + # # + # Form Fields # + # # + ######################## + + def _formFieldBindings(self): + bindings = {} + prevDesc = cmdnames.FORM_FIELD_PREV + bindings["previous"] = ["f", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.FORM_FIELD_NEXT + bindings["next"] = ["f", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.FORM_FIELD_LIST + bindings["list"] = ["f", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _formFieldGetter(self, document, arg=None): + def is_not_noneditable_doc_frame(obj): + if AXUtilities.is_document_frame(obj): + return AXUtilities.is_editable(obj) + return True + return AXUtilities.find_all_form_fields(document, pred=is_not_noneditable_doc_frame) + + def _formFieldPresentation(self, obj, arg=None): + if obj is not None: + if AXUtilities.is_text(obj) and AXObject.get_child_count(obj): + obj = AXObject.get_child(obj, 0) + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_FORM_FIELDS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _formFieldDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LABEL] + columnHeaders.append(guilabels.SN_HEADER_ROLE) + columnHeaders.append(guilabels.SN_HEADER_VALUE) + + def rowData(obj): + return [self._getLabel(obj), + self._getRoleName(obj), + self._getValue(obj)] + + return guilabels.SN_TITLE_FORM_FIELD, columnHeaders, rowData + + ######################## + # # + # Headings # + # # + ######################## + + def _headingBindings(self): + bindings = {} + prevDesc = cmdnames.HEADING_PREV + bindings["previous"] = ["h", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.HEADING_NEXT + bindings["next"] = ["h", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.HEADING_LIST + bindings["list"] = ["h", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + + prevAtLevelBindings = [] + nextAtLevelBindings = [] + listAtLevelBindings = [] + minLevel, maxLevel = self._headingLevels() + for i in range(minLevel, maxLevel + 1): + prevDesc = cmdnames.HEADING_AT_LEVEL_PREV % i + prevAtLevelBindings.append([str(i), + keybindings.SHIFT_MODIFIER_MASK, + prevDesc]) + + nextDesc = cmdnames.HEADING_AT_LEVEL_NEXT % i + nextAtLevelBindings.append([str(i), + keybindings.NO_MODIFIER_MASK, + nextDesc]) + + listDesc = cmdnames.HEADING_AT_LEVEL_LIST %i + listAtLevelBindings.append([str(i), + keybindings.SHIFT_ALT_MODIFIER_MASK, + listDesc]) + + bindings["previousAtLevel"] = prevAtLevelBindings + bindings["nextAtLevel"] = nextAtLevelBindings + bindings["listAtLevel"] = listAtLevelBindings + + return bindings + + def _headingLevels(self): + return [1, 6] + + def _headingGetter(self, document, arg=None): + if arg is not None: + return AXUtilities.find_all_headings_at_level(document, level=arg) + return AXUtilities.find_all_headings(document) + + def _headingPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + elif arg is None: + full = messages.NO_MORE_HEADINGS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + else: + full = messages.NO_MORE_HEADINGS_AT_LEVEL % arg + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _headingDialogData(self, arg=None): + columnHeaders = [guilabels.SN_HEADER_HEADING] + + if not arg: + title = guilabels.SN_TITLE_HEADING + columnHeaders.append(guilabels.SN_HEADER_LEVEL) + + def rowData(obj): + return [self._getText(obj), + str(self._script.utilities.headingLevel(obj))] + + else: + title = guilabels.SN_TITLE_HEADING_AT_LEVEL % arg + + def rowData(obj): + return [self._getText(obj)] + + return title, columnHeaders, rowData + + ######################## + # # + # Iframes # + # # + ######################## + + def _iframeBindings(self): + bindings = {} + prevDesc = cmdnames.IFRAME_PREV + bindings["previous"] = ["", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.IFRAME_NEXT + bindings["next"] = ["", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.IFRAME_LIST + bindings["list"] = ["", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _iframeGetter(self, document, arg=None): + return AXUtilities.find_all_internal_frames(document) + + def _iframePresentation(self, obj, arg=None): + if obj is not None: + [newObj, characterOffset] = self._getCaretPosition(obj) + self._setCaretPosition(newObj, characterOffset) + self._presentObject(obj, 0) + else: + full = messages.NO_MORE_IFRAMES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _iframeDialogData(self): + columnHeaders = [guilabels.SN_HEADER_IFRAME] + + def rowData(obj): + name = AXObject.get_name(obj) + if not name and AXObject.get_child_count(obj): + name = AXObject.get_name(AXObject.get_child(obj, 0)) + return [name or self._getRoleName(obj)] + + return guilabels.SN_TITLE_IFRAME, columnHeaders, rowData + + ######################## + # # + # Images # + # # + ######################## + + def _imageBindings(self): + bindings = {} + prevDesc = cmdnames.IMAGE_PREV + bindings["previous"] = ["g", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.IMAGE_NEXT + bindings["next"] = ["g", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.IMAGE_LIST + bindings["list"] = ["g", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _imageGetter(self, document, arg=None): + return AXUtilities.find_all_images_and_image_maps(document) + + def _imagePresentation(self, obj, arg=None): + if obj is not None: + [newObj, characterOffset] = self._getCaretPosition(obj) + self._setCaretPosition(newObj, characterOffset) + self._presentObject(obj, 0) + else: + full = messages.NO_MORE_IMAGES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _imageDialogData(self): + columnHeaders = [guilabels.SN_HEADER_IMAGE] + + def rowData(obj): + return [self._getText(obj) or self._getRoleName(obj)] + + return guilabels.SN_TITLE_IMAGE, columnHeaders, rowData + + ######################## + # # + # Landmarks # + # # + ######################## + + def _landmarkBindings(self): + bindings = {} + prevDesc = cmdnames.LANDMARK_PREV + bindings["previous"] = ["m", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.LANDMARK_NEXT + bindings["next"] = ["m", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.LANDMARK_LIST + bindings["list"] = ["m", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _landmarkGetter(self, document, arg=None): + return AXUtilities.find_all_landmarks(document) + + def _landmarkPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._script.presentMessage(AXObject.get_name(obj)) + self._presentLine(obj, characterOffset) + else: + full = messages.NO_LANDMARK_FOUND + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _landmarkDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LANDMARK] + columnHeaders.append(guilabels.SN_HEADER_ROLE) + + def rowData(obj): + return [AXObject.get_name(obj), self._getRoleName(obj)] + + return guilabels.SN_TITLE_LANDMARK, columnHeaders, rowData + + ######################## + # # + # Lists # + # # + ######################## + + def _listBindings(self): + bindings = {} + prevDesc = cmdnames.LIST_PREV + bindings["previous"] = ["l", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.LIST_NEXT + bindings["next"] = ["l", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.LIST_LIST + bindings["list"] = ["l", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _listGetter(self, document, arg=None): + return AXUtilities.find_all_lists(document) + + def _listPresentation(self, obj, arg=None): + if obj is not None: + self._script.speakMessage(self._getListDescription(obj)) + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentLine(obj, characterOffset) + else: + full = messages.NO_MORE_LISTS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _listDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LIST] + + def rowData(obj): + return [self._getText(obj)] + + return guilabels.SN_TITLE_LIST, columnHeaders, rowData + + ######################## + # # + # List Items # + # # + ######################## + + def _listItemBindings(self): + bindings = {} + prevDesc = cmdnames.LIST_ITEM_PREV + bindings["previous"] = ["i", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.LIST_ITEM_NEXT + bindings["next"] = ["i", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.LIST_ITEM_LIST + bindings["list"] = ["i", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _listItemGetter(self, document, arg=None): + return AXUtilities.find_all_list_items(document) + + def _listItemPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentLine(obj, characterOffset) + else: + full = messages.NO_MORE_LIST_ITEMS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _listItemDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LIST_ITEM] + + def rowData(obj): + return [self._getText(obj)] + + return guilabels.SN_TITLE_LIST_ITEM, columnHeaders, rowData + + ######################## + # # + # Live Regions # + # # + ######################## + + def _liveRegionBindings(self): + bindings = {} + prevDesc = cmdnames.LIVE_REGION_PREV + bindings["previous"] = ["d", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.LIVE_REGION_NEXT + bindings["next"] = ["d", keybindings.NO_MODIFIER_MASK, nextDesc] + + desc = cmdnames.LIVE_REGION_LAST + bindings["last"] = ["y", keybindings.NO_MODIFIER_MASK, desc] + return bindings + + def _liveRegionGetter(self, document, arg=None): + return AXUtilities.find_all_live_regions(document) + + def _liveRegionPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_LIVE_REGIONS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + ######################## + # # + # Paragraphs # + # # + ######################## + + def _paragraphBindings(self): + bindings = {} + prevDesc = cmdnames.PARAGRAPH_PREV + bindings["previous"] = ["p", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.PARAGRAPH_NEXT + bindings["next"] = ["p", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.PARAGRAPH_LIST + bindings["list"] = ["p", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _paragraphGetter(self, document, arg=None): + def has_at_least_three_characters(obj): + if AXUtilities.is_heading(obj): + return True + + try: + text = obj.queryText() + # We're choosing 3 characters as the minimum because some + # paragraphs contain a single image or link and a text + # of length 2: An embedded object character and a space. + # We want to skip these. + return text.characterCount > 2 + except Exception: + return False + + return AXUtilities.find_all_paragraphs(document, True, has_at_least_three_characters) + + def _paragraphPresentation(self, obj, arg=None): + if obj is not None: + [newObj, characterOffset] = self._getCaretPosition(obj) + self._setCaretPosition(newObj, characterOffset) + self._presentObject(obj, 0) + else: + full = messages.NO_MORE_PARAGRAPHS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _paragraphDialogData(self): + columnHeaders = [guilabels.SN_HEADER_PARAGRAPH] + + def rowData(obj): + return [self._getText(obj)] + + return guilabels.SN_TITLE_PARAGRAPH, columnHeaders, rowData + + ######################## + # # + # Radio Buttons # + # # + ######################## + + def _radioButtonBindings(self): + bindings = {} + prevDesc = cmdnames.RADIO_BUTTON_PREV + bindings["previous"] = ["r", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.RADIO_BUTTON_NEXT + bindings["next"] = ["r", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.RADIO_BUTTON_LIST + bindings["list"] = ["r", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _radioButtonGetter(self, document, arg=None): + return AXUtilities.find_all_radio_buttons(document) + + def _radioButtonPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_RADIO_BUTTONS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _radioButtonDialogData(self): + columnHeaders = [guilabels.SN_HEADER_RADIO_BUTTON] + columnHeaders.append(guilabels.SN_HEADER_STATE) + + def rowData(obj): + return [self._getLabel(obj), self._getState(obj)] + + return guilabels.SN_TITLE_RADIO_BUTTON, columnHeaders, rowData + + ######################## + # # + # Separators # + # # + ######################## + + def _separatorBindings(self): + bindings = {} + prevDesc = cmdnames.SEPARATOR_PREV + bindings["previous"] = ["s", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.SEPARATOR_NEXT + bindings["next"] = ["s", keybindings.NO_MODIFIER_MASK, nextDesc] + return bindings + + def _separatorGetter(self, document, arg=None): + return AXUtilities.find_all_separators(document) + + def _separatorPresentation(self, obj, arg=None): + if obj is not None: + [newObj, characterOffset] = self._getCaretPosition(obj) + self._setCaretPosition(newObj, characterOffset) + self._presentObject(obj, 0) + else: + full = messages.NO_MORE_SEPARATORS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + ######################## + # # + # Tables # + # # + ######################## + + def _tableBindings(self): + bindings = {} + prevDesc = cmdnames.TABLE_PREV + bindings["previous"] = ["t", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.TABLE_NEXT + bindings["next"] = ["t", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.TABLE_LIST + bindings["list"] = ["t", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _tableGetter(self, document, arg=None): + def is_not_layout_or_empty(obj): + if not AXObject.get_child_count(obj): + return False + + # This should no longer be needed once Atspi 2.8.4 is released. + attrs = self._script.utilities.objectAttributes(obj) + if attrs.get('layout-guess') == 'true': + return False + + try: + return obj.queryTable().nRows > 0 + except Exception: + return False + + return AXUtilities.find_all_tables(document, is_not_layout_or_empty) + + def _tablePresentation(self, obj, arg=None): + if obj is not None: + caption = self._getTableCaption(obj) + if caption: + self._script.presentMessage(caption) + self._script.presentMessage(self._getTableDescription(obj)) + cell = obj.queryTable().getAccessibleAt(0, 0) + if not cell: + tokens = ["STRUCTURAL NAVIGATION: Broken table interface for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + cell = AXObject.find_descendant(obj, AXUtilities.is_table_cell) + if cell: + tokens = ["STRUCTURAL NAVIGATION: Located", cell, "for first cell"] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + self.lastTableCell = [0, 0] + self._presentObject(cell, 0, priorObj=obj) + [cell, characterOffset] = self._getCaretPosition(cell) + self._setCaretPosition(cell, characterOffset) + else: + full = messages.NO_MORE_TABLES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _tableDialogData(self): + columnHeaders = [guilabels.SN_HEADER_CAPTION] + columnHeaders.append(guilabels.SN_HEADER_DESCRIPTION) + + def rowData(obj): + return [self._getTableCaption(obj) or '', + self._getTableDescription(obj)] + + return guilabels.SN_TITLE_TABLE, columnHeaders, rowData + + ######################## + # # + # Table Cells # + # # + ######################## + + def _tableCellBindings(self): + bindings = {} + desc = cmdnames.TABLE_CELL_LEFT + bindings["left"] = ["Left", keybindings.SHIFT_ALT_MODIFIER_MASK, desc] + + desc = cmdnames.TABLE_CELL_RIGHT + bindings["right"] = ["Right", keybindings.SHIFT_ALT_MODIFIER_MASK, desc] + + desc = cmdnames.TABLE_CELL_UP + bindings["up"] = ["Up", keybindings.SHIFT_ALT_MODIFIER_MASK, desc] + + desc = cmdnames.TABLE_CELL_DOWN + bindings["down"] = ["Down", keybindings.SHIFT_ALT_MODIFIER_MASK, desc] + + desc = cmdnames.TABLE_CELL_FIRST + bindings["first"] = ["Home", keybindings.SHIFT_ALT_MODIFIER_MASK, desc] + + desc = cmdnames.TABLE_CELL_LAST + bindings["last"] = ["End", keybindings.SHIFT_ALT_MODIFIER_MASK, desc] + return bindings + + def _tableCellGetter(self, document, arg=None): + # TODO - JD: It would be more performant to set the root to the table. + # Actually, this doesn't seem to be getting used. Either use it or delete it. + return AXUtilities.find_all_table_cells_and_headers(document) + + def _tableCellPresentation(self, cell, arg): + if cell is None: + return + + if settings.speakCellHeaders: + self._presentCellHeaders(cell, arg) + + [obj, characterOffset] = self._getCaretPosition(cell) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._script.updateBraille(obj) + + blank = self._isBlankCell(cell) + if not blank: + self._presentObject(cell, 0) + else: + self._script.speakMessage(messages.BLANK) + + if settings.speakCellCoordinates: + [row, col] = self.getCellCoordinates(cell) + self._script.presentMessage(messages.TABLE_CELL_COORDINATES \ + % {"row" : row + 1, "column" : col + 1}) + + rowspan, colspan = self._script.utilities.rowAndColumnSpan(cell) + spanString = messages.cellSpan(rowspan, colspan) + if spanString and settings.speakCellSpan: + self._script.presentMessage(spanString) + + ######################## + # # + # Unvisited Links # + # # + ######################## + + def _unvisitedLinkBindings(self): + bindings = {} + prevDesc = cmdnames.UNVISITED_LINK_PREV + bindings["previous"] = ["u", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.UNVISITED_LINK_NEXT + bindings["next"] = ["u", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.UNVISITED_LINK_LIST + bindings["list"] = ["u", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + + return bindings + + def _unvisitedLinkGetter(self, document, arg=None): + return AXUtilities.find_all_unvisited_links(document) + + def _unvisitedLinkPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_UNVISITED_LINKS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _unvisitedLinkDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LINK] + columnHeaders.append(guilabels.SN_HEADER_URI) + + def rowData(obj): + return [self._getText(obj), self._script.utilities.uri(obj)] + + return guilabels.SN_TITLE_UNVISITED_LINK, columnHeaders, rowData + + ######################## + # # + # Visited Links # + # # + ######################## + + def _visitedLinkBindings(self): + bindings = {} + prevDesc = cmdnames.VISITED_LINK_PREV + bindings["previous"] = ["v", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.VISITED_LINK_NEXT + bindings["next"] = ["v", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.VISITED_LINK_LIST + bindings["list"] = ["v", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + + return bindings + + def _visitedLinkGetter(self, document, arg=None): + return AXUtilities.find_all_visited_links(document) + + def _visitedLinkPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_VISITED_LINKS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _visitedLinkDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LINK] + columnHeaders.append(guilabels.SN_HEADER_URI) + + def rowData(obj): + return [self._getText(obj), self._script.utilities.uri(obj)] + + return guilabels.SN_TITLE_VISITED_LINK, columnHeaders, rowData + + ######################## + # # + # Plain ol' Links # + # # + ######################## + + def _linkBindings(self): + bindings = {} + prevDesc = cmdnames.LINK_PREV + bindings["previous"] = ["k", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.LINK_NEXT + bindings["next"] = ["k", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.LINK_LIST + bindings["list"] = ["k", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _linkGetter(self, document, arg=None): + return AXUtilities.find_all_links(document) + + def _linkPresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + else: + full = messages.NO_MORE_LINKS + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _linkDialogData(self): + columnHeaders = [guilabels.SN_HEADER_LINK] + columnHeaders.append(guilabels.SN_HEADER_STATE) + columnHeaders.append(guilabels.SN_HEADER_URI) + + def rowData(obj): + return [self._getText(obj), + self._getState(obj), + self._script.utilities.uri(obj)] + + return guilabels.SN_TITLE_LINK, columnHeaders, rowData + + ######################## + # # + # Clickables # + # # + ######################## + + def _clickableBindings(self): + bindings = {} + prevDesc = cmdnames.CLICKABLE_PREV + bindings["previous"] = ["a", keybindings.SHIFT_MODIFIER_MASK, prevDesc] + + nextDesc = cmdnames.CLICKABLE_NEXT + bindings["next"] = ["a", keybindings.NO_MODIFIER_MASK, nextDesc] + + listDesc = cmdnames.CLICKABLE_LIST + bindings["list"] = ["a", keybindings.SHIFT_ALT_MODIFIER_MASK, listDesc] + return bindings + + def _clickableCriteria(self, arg=None): + return AXCollection.create_match_rule( + interfaces=["action"], + interface_match_type=Atspi.CollectionMatchType.ANY) + + def _clickablePredicate(self, obj, arg=None): + return self._script.utilities.isClickableElement(obj) + + def _clickablePresentation(self, obj, arg=None): + if obj is not None: + [obj, characterOffset] = self._getCaretPosition(obj) + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentObject(obj, characterOffset) + elif not arg: + full = messages.NO_MORE_CLICKABLES + brief = messages.STRUCTURAL_NAVIGATION_NOT_FOUND + self._script.presentMessage(full, brief) + + def _clickableDialogData(self): + columnHeaders = [guilabels.SN_HEADER_CLICKABLE] + columnHeaders.append(guilabels.SN_HEADER_ROLE) + + def rowData(obj): + return [self._getText(obj), self._getRoleName(obj)] + + return guilabels.SN_TITLE_CLICKABLE, columnHeaders, rowData + + ######################## + # # + # Containers # + # # + ######################## + + def _containerBindings(self): + bindings = {} + desc = cmdnames.CONTAINER_START + bindings["start"] = ["comma", keybindings.SHIFT_MODIFIER_MASK, desc] + + desc = cmdnames.CONTAINER_END + bindings["end"] = ["comma", keybindings.NO_MODIFIER_MASK, desc] + + return bindings + + def _containerCriteria(self, arg=None): + return AXCollection.create_match_rule(roles=self.CONTAINER_ROLES) + + def _containerPredicate(self, obj, arg=None): + return self._isContainer(obj) + + def _containerPresentation(self, obj, arg=None, **kwargs): + if obj is None: + self._script.presentMessage(messages.CONTAINER_NOT_IN_A) + return + + if kwargs.get("sameContainer"): + self._script.presentMessage(messages.CONTAINER_END) + + characterOffset = arg + if characterOffset is None: + obj, characterOffset = self._getCaretPosition(obj) + + obj, characterOffset = self._setCaretPosition(obj, characterOffset) + self._presentLine(obj, characterOffset) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/text_attribute_names.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/text_attribute_names.py new file mode 100644 index 0000000..2c19cf7 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/text_attribute_names.py @@ -0,0 +1,784 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Provides getTextAttributeName method that maps each text attribute +into its localized equivalent.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2008 Sun Microsystems Inc." +__license__ = "LGPL" + +from .cthulhu_i18n import C_ + +# Translators: this is a structure to assist in the generation of +# localized strings for the various text attributes. +# +# Information can be found in the Atk documentation at: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +# The at-spi IDL documentation for Accessibility_Text.idl also provides +# the following information: +# +# Attributes relevant to localization should be provided in accordance +# with the w3c "Internationalization and Localization Markup Requirements", +# http://www.w3.org/TR/2005/WD-itsreq-20051122/ +# +# Other text attributes should choose their names and value semantics in +# accordance with relevant standards such as: +# CSS level 2 (http://www.w3.org/TR/1998/REC-CSS2-19980512), +# XHTML 1.0 (http://www.w3.org/TR/2002/REC-xhtml1-20020801), and +# WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). +# +# Where possible, specific URL references will also be given below for +# each text attribute. +# + +_textAttributeTable = {} + +# Translators: this attribute specifies the background color of the text. +# The value is an RGB value of the format "u,u,u". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["bg-color"] = C_("textattr", "background color") + +# Translators: this attribute specifies whether to make the background +# color for each character the height of the highest font used on the +# current line, or the height of the font used for the current character. +# It will be a "true" or "false" value. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["bg-full-height"] = C_("textattr", "background full height") + +# Translators: this attribute specifies whether a GdkBitmap is set for +# stippling the background color. It will be a "true" or "false" value. +# See +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["bg-stipple"] = C_("textattr", "background stipple") + +# Translators: this attribute specifies the direction of the text. +# Values are "none", "ltr" or "rtl". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["direction"] = C_("textattr", "direction") + +# Translators: this attribute specifies whether the text is editable. +# It will be a "true" or "false" value. +# See +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["editable"] = C_("textattr", "editable") + +# Translators: this attribute specifies the font family name of the text. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["family-name"] = C_("textattr", "family name") + +# Translators: this attribute specifies the foreground color of the text. +# The value is an RGB value of the format "u,u,u". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["fg-color"] = C_("textattr", "foreground color") + +# Translators: this attribute specifies whether a GdkBitmap is set for +# stippling the foreground color. It will be a "true" or "false" value. +# See +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["fg-stipple"] = C_("textattr", "foreground stipple") + +# Translators: this attribute specifies the effect applied to the font +# used by the text. +# See: +# http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["font-effect"] = C_("textattr", "font effect") + +# Translators: this attribute specifies the indentation of the text +# (in pixels). +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["indent"] = C_("textattr", "indent") + +# Translators: this attribute specifies there is something "wrong" with +# the text, such as it being a misspelled word. See: +# https://developer.mozilla.org/en/Accessibility/AT-APIs/Gecko/TextAttrs +# +_textAttributeTable["invalid"] = C_("textattr", "mistake") +# Translators: this attribute specifies there is something "wrong" with +# the text, such as it being a misspelled word. See: +# https://developer.mozilla.org/en/Accessibility/AT-APIs/Gecko/TextAttrs +# + +# Translators: this attribute specifies whether the text is invisible. +# It will be a "true" or "false" value. +# See +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["invisible"] = C_("textattr", "invisible") + +# Translators: this attribute specifies how the justification of the text. +# Values are "left", "right", "center" or "fill". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["justification"] = C_("textattr", "justification") + +# Translators: this attribute specifies the language that the text is +# written in. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["language"] = C_("textattr", "language") + +# Translators: this attribute specifies the pixel width of the left margin. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["left-margin"] = C_("textattr", "left margin") + +# Translators: this attribute specifies the height of the line of text. +# See: +# http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-line-height +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["line-height"] = C_("textattr", "line height") + +# Translators: this attribute refers to the named style which is associated +# with the entire paragraph and which controls the default formatting +# (font, text size, alignment, etc.) of that paragraph. Examples of +# paragraph styles include "Heading 1", "Heading 2", "Caption", "Footnote", +# "Text Body", "Title", and "Subtitle". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["paragraph-style"] = C_("textattr", "paragraph style") + +# Translators: this attribute specifies the pixels of blank space to +# leave above each newline-terminated line. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["pixels-above-lines"] = C_("textattr", "pixels above lines") + +# Translators: this attribute specifies the pixels of blank space to +# leave below each newline-terminated line. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["pixels-below-lines"] = C_("textattr", "pixels below lines") + +# Translators: this attribute specifies the pixels of blank space to +# leave between wrapped lines inside the same newline-terminated line +# (paragraph). +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["pixels-inside-wrap"] = C_("textattr", "pixels inside wrap") + +# Translators: this attribute specifies the pixel width of the right margin. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["right-margin"] = C_("textattr", "right margin") + +# Translators: this attribute specifies the number of pixels that the +# text characters are risen above the baseline. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["rise"] = C_("textattr", "rise") + +# Translators: this attribute specifies the scale of the characters. The +# value is a string representation of a double. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["scale"] = C_("textattr", "scale") + +# Translators: this attribute specifies the size of the text. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["size"] = C_("textattr", "size") + +# Translators: this attribute specifies the stretch of he text, if set. +# Values are "ultra_condensed", "extra_condensed", "condensed", +# "semi_condensed", "normal", "semi_expanded", "expanded", +# "extra_expanded" or "ultra_expanded". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["stretch"] = C_("textattr", "stretch") + +# Translators: this attribute specifies whether the text is strike though +# (in other words, whether there is a line drawn through it). Values are +# "true" or "false". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["strikethrough"] = C_("textattr", "strike through") + +# Translators: this attribute specifies the slant style of the text, +# if set. Values are "normal", "oblique" or "italic". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["style"] = C_("textattr", "style") + +# Translators: this attribute specifies the decoration of the text. +# See: +# http://www.w3.org/TR/1998/REC-CSS2-19980512/text.html#propdef-text-decoration +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["text-decoration"] = C_("textattr", "text decoration") + +# Translators: this attribute specifies the angle at which the text is +# displayed (i.e. rotated from the norm) and is represented in degrees +# of rotation. +# See: +# http://www.w3.org/TR/2003/CR-css3-text-20030514/#glyph-orientation-horizontal +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["text-rotation"] = C_("textattr", "text rotation") + +# Translators: this attribute specifies the shadow effects applied to the text. +# See: +# http://www.w3.org/TR/1998/REC-CSS2-19980512/text.html#propdef-text-shadow +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["text-shadow"] = C_("textattr", "text shadow") + +# Translators: this attributes specifies whether the text is underlined. +# Values are "none", "single", "double" or "low". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["underline"] = C_("textattr", "underline") + +# Translators: this attribute specifies the capitalization variant of +# the text, if set. Values are "normal" or "small_caps". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["variant"] = C_("textattr", "variant") + +# Translators: this attributes specifies what vertical alignment property +# has been applied to the text. +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["vertical-align"] = C_("textattr", "vertical align") + +# Translators: this attribute specifies the weight of the text. +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# http://www.w3.org/TR/1998/REC-CSS2-19980512/fonts.html#propdef-font-weight +# +_textAttributeTable["weight"] = C_("textattr", "weight") + +# Translators: this attribute specifies the wrap mode of the text, if any. +# Values are "none", "char" or "word". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["wrap-mode"] = C_("textattr", "wrap mode") + +# Translators: this attribute specifies the way the text is written. +# Values are "lr-tb", "rl-tb", "tb-rl", "tb-lr", "bt-rl", "bt-lr", "lr", +# "rl" and "tb". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["writing-mode"] = C_("textattr", "writing mode") + + +# The following are the known values of some of these text attributes. +# These values were found in the Atk documentation at: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# No doubt there will be more, and as they are found, they can be added +# to this table so they can be translated. +# + +# Translators: this is one of the text attribute values for the following +# text attributes: "invisible", "editable", bg-full-height", "strikethrough", +# "bg-stipple" and "fg-stipple". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["true"] = C_("textattr", "true") + +# Translators: this is one of the text attribute values for the following +# text attributes: "invisible", "editable", bg-full-height", "strikethrough", +# "bg-stipple" and "fg-stipple". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["false"] = C_("textattr", "false") + +# Translators: this is one of the text attribute values for the following +# text attributes: "font-effect", "underline", "text-shadow", "wrap mode" +# and "direction". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["none"] = C_("textattr", "none") + +# Translators: this is one of the text attribute values for the following +# text attributes: "font-effect". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["engrave"] = C_("textattr", "engrave") + +# Translators: this is one of the text attribute values for the following +# text attributes: "font-effect". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["emboss"] = C_("textattr", "emboss") + +# Translators: this is one of the text attribute values for the following +# text attributes: "font-effect". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["outline"] = C_("textattr", "outline") + +# Translators: this is one of the text attribute values for the following +# text attributes: "text-decoration". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["overline"] = C_("textattr", "overline") + +# Translators: this is one of the text attribute values for the following +# text attributes: "text-decoration". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["line-through"] = C_("textattr", "line through") + +# Translators: this is one of the text attribute values for the following +# text attributes: "text-decoration". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["blink"] = C_("textattr", "blink") + +# Translators: this is one of the text attribute values for the following +# text attributes: "text-shadow". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["black"] = C_("textattr", "black") + +# Translators: this is one of the text attribute values for the following +# text attributes: "underline". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["single"] = C_("textattr", "single") + +# Translators: this is one of the text attribute values for the following +# text attributes: "underline". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["double"] = C_("textattr", "double") + +# Translators: this is one of the text attribute values for the following +# text attributes: "underline". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["low"] = C_("textattr", "low") + +# Translators: this is one of the text attribute values for the following +# text attributes: "wrap mode". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["char"] = C_("textattr", "char") + +# Translators: this is one of the text attribute values for the following +# text attributes: "wrap mode". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["word"] = C_("textattr", "word") + +# Translators: this is one of the text attribute values for the following +# text attributes: "wrap mode." It corresponds to GTK_WRAP_WORD_CHAR, +# defined in the Gtk documentation as "Wrap text, breaking lines in +# between words, or if that is not enough, also between graphemes." +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# http://library.gnome.org/devel/gtk/stable/GtkTextTag.html#GtkWrapMode +# +_textAttributeTable["word_char"] = C_("textattr", "word char") + +# Translators: this is one of the text attribute values for the following +# text attributes: "direction". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["ltr"] = C_("textattr", "ltr") + +# Translators: this is one of the text attribute values for the following +# text attributes: "direction". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["rtl"] = C_("textattr", "rtl") + +# Translators: this is one of the text attribute values for the following +# text attributes: "justification". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["left"] = C_("textattr", "left") + +# Translators: this is one of the text attribute values for the following +# text attributes: "justification". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["right"] = C_("textattr", "right") + +# Translators: this is one of the text attribute values for the following +# text attributes: "justification". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["center"] = C_("textattr", "center") + +# Translators: this is one of the text attribute values for the following +# text attributes: "justification". In Gecko, when no justification has +# be explicitly set, they report a justification of "start". +# +_textAttributeTable["start"] = C_("textattr", "no justification") + +# Translators: this is one of the text attribute values for the following +# text attributes: "justification". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["fill"] = C_("textattr", "fill") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["ultra_condensed"] = C_("textattr", "ultra condensed") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["extra_condensed"] = C_("textattr", "extra condensed") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["condensed"] = C_("textattr", "condensed") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["semi_condensed"] = C_("textattr", "semi condensed") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch" and "variant". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["normal"] = C_("textattr", "normal") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["semi_expanded"] = C_("textattr", "semi expanded") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["expanded"] = C_("textattr", "expanded") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["extra_expanded"] = C_("textattr", "extra expanded") + +# Translators: this is one of the text attribute values for the following +# text attributes: "stretch". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["ultra_expanded"] = C_("textattr", "ultra expanded") + +# Translators: this is one of the text attribute values for the following +# text attributes: "variant". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["small_caps"] = C_("textattr", "small caps") + +# Translators: this is one of the text attribute values for the following +# text attributes: "style". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["oblique"] = C_("textattr", "oblique") + +# Translators: this is one of the text attribute values for the following +# text attributes: "style". +# See: +# http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute +# +_textAttributeTable["italic"] = C_("textattr", "italic") + +# Translators: this is one of the text attribute values for the following +# text attributes: "paragraph-style". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["Default"] = C_("textattr", "Default") + +# Translators: this is one of the text attribute values for the following +# text attributes: "paragraph-style". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["Text body"] = C_("textattr", "Text body") + +# Translators: this is one of the text attribute values for the following +# text attributes: "paragraph-style". +# See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["Heading"] = C_("textattr", "Heading") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["baseline"] = C_("textattr", "baseline") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["sub"] = C_("textattr", "sub") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["super"] = C_("textattr", "super") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["top"] = C_("textattr", "top") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["text-top"] = C_("textattr", "text-top") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["middle"] = C_("textattr", "middle") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["bottom"] = C_("textattr", "bottom") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# +_textAttributeTable["text-bottom"] = C_("textattr", "text-bottom") + +# Translators: this is one of the text attribute values for the following +# text attributes: "vertical-align" and "writing-mode". +# See: +#http://www.w3.org/TR/1998/REC-CSS2-19980512/visudet.html#propdef-vertical-align +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["inherit"] = C_("textattr", "inherit") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["lr-tb"] = C_("textattr", "lr-tb") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["rl-tb"] = C_("textattr", "rl-tb") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["tb-rl"] = C_("textattr", "tb-rl") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["tb-lr"] = C_("textattr", "tb-lr") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["bt-rl"] = C_("textattr", "bt-rl") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["bt-lr"] = C_("textattr", "bt-lr") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["lr"] = C_("textattr", "lr") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["rl"] = C_("textattr", "rl") + +# Translators: this is one of the text attribute values for the following +# text attributes: "writing-mode". +# See: +# http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection +# +_textAttributeTable["tb"] = C_("textattr", "tb") + +# Translators: this is one of the text attribute values for the following +# text attributes: "strikethrough." It refers to the line style. +# +_textAttributeTable["solid"] = C_("textattr", "solid") + +# Translators: this is one of the text attribute values for the following +# text attributes: "invalid". It is an indication that the text is not +# spelled correctly. See: +# https://developer.mozilla.org/en/Accessibility/AT-APIs/Gecko/TextAttrs +# +_textAttributeTable["spelling"] = C_("textattr", "spelling") + +# Translators: This is the text-spelling attribute. See: +# http://wiki.services.openoffice.org/wiki/Accessibility/TextAttributes +# +_textAttributeTable["text-spelling"] = C_("textattr", "spelling") + +def getTextAttributeKey(localizedTextAttr): + """Given a localized text attribute, return the original text + attribute, (i.e. the key value). + + Arguments: + - localizedTextAttr: the localized text attribute. + + Returns a string representing the original text attribute key for the + localized text attribute. + """ + + for key, value in _textAttributeTable.items(): + if value == localizedTextAttr: + return key + + return localizedTextAttr + +def getTextAttributeName(textAttr, script=None): + """Given a text attribute, returns its localized equivalent. + + Arguments: + - textAttr: the text attribute to get the localized equivalent of. + + Returns a string representing the localized equivalent for the text + attribute. + """ + + # Normalize the name to an Atk name before attempting to look it up. + # + if script: + textAttr = script.utilities.getAtkNameForAttribute(textAttr) + + return _textAttributeTable.get(textAttr, textAttr) diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_context.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_context.py new file mode 100644 index 0000000..aac71ac --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_context.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import gi, os, locale, gettext +from gi.repository import GObject +import gettext + +from cthulhu import cthulhu_i18n + +class TranslationContext(): + def __init__(self, app): + self.app = app + self.localeDir = cthulhu_i18n.localedir + self.domain = 'cthulhu' + self.language = 'en' + self.fallbackToCthulhuTranslation = True + self.domainTranslation = None + self.cthulhuMainTranslation = None + + def setDomain(self, domain): + self.domain = domain + def setLanguage(self, language): + self.language = language + def setLocaleDir(self, localeDir): + self.localeDir = localeDir + def getCurrentDefaultLocale(self): + return locale.getdefaultlocale()[0] + def setFallbackToCthulhuTranslation(self, fallback): + self.fallback = fallback + def getFallbackToCthulhuTranslation(self): + return self.fallback + def getLocaleDir(self): + return self.localeDir + def getLanguage(self): + return self.language + def getDomain(self): + return self.domain + def getDomainTranslation(self): + return self.domainTranslation + def getCthulhuMainTranslation(self): + return self.cthulhuMainTranslation + def setDomainTranslation(self, domainTranslation): + self.domainTranslation = domainTranslation + def setCthulhuMainTranslation(self, cthulhuMainTranslation): + self.cthulhuMainTranslation = cthulhuMainTranslation + def updateTranslation(self): + self.setDomainTranslation(None) + self.setCthulhuMainTranslation(None) + + try: + self.setLanguage(self.getCurrentDefaultLocale()) + except: + self.setLanguage('en') + print(e) + if self.getFallbackToCthulhuTranslation(): + cthulhuaMainTranslation = cthulhu_i18n + self.setCthulhuMainTranslation(cthulhuaMainTranslation) + try: + domainTranslation = gettext.translation(self.getDomain(), self.getLocaleDir(), languages=[self.getLanguage()]) + self.setDomainTranslation(domainTranslation) + except Exception as e: + print(e) + + def gettext(self, text): + translatedText = text + if self.getDomainTranslation() != None: + try: + translatedText = self.getDomainTranslation().gettext(text) + except Exception as e: + print(e) + if translatedText == text: + if self.getFallbackToCthulhuTranslation() or self.getDomainTranslation() == None: + if self.getCthulhuMainTranslation() != None: + try: + translatedText = self.getCthulhuMainTranslation().cgettext(text) # gettext from cthulhu_i18n + except Exception as e: + print(e) + return translatedText + + def ngettext(self, singular, plural, n): + translatedText = singular + if n > 1: + translatedText = plural + if self.getDomainTranslation() != None: + try: + translatedText = self.getDomainTranslation().ngettext(singular, plural, n) + except: + pass + if translatedText in [singular, plural]: # not translated + if self.getFallbackToCthulhuTranslation() or self.getDomainTranslation() == None: + if self.getCthulhuMainTranslation() != None: + try: + translatedText = self.getCthulhuMainTranslation().ngettext(singular, plural, n) + except: + pass + return translatedText diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_manager.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_manager.py new file mode 100644 index 0000000..8265581 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/translation_manager.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +import gi, os, locale, gettext +from gi.repository import GObject +import gettext + +from cthulhu import cthulhu_i18n +from cthulhu import translation_context + +class TranslationManager(): + def __init__(self, app): + self.app = app + self.translatioContextnDict = {} + def initTranslation(self, name, domain = None, localeDir = None, language = None, fallbackToCthulhuTranslation = True): + translationContext = translation_context.TranslationContext(self.app) + if os.path.isdir(localeDir): + translationContext.setDomain(domain) + translationContext.setLocaleDir(localeDir) + translationContext.setLanguage(language) + translationContext.setFallbackToCthulhuTranslation(fallbackToCthulhuTranslation) + translationContext.updateTranslation() + self.addTranslationDict(name, translationContext) + return translationContext + def addTranslationDict(self, name, translationContext): + self.translatioContextnDict[name] = translationContext + def getTranslationContextByName(name): + try: + return self.translatioContextnDict[name] + except KeyError: + return self.translatioContextnDict['cthulhu'] + #def getTranslationsInstance(self, domain='cthulhu'): + """ Gets the gettext translation instance for this add-on. + \\locale will be used to find .mo files, if exists. + If a translation file is not found the default fallback null translation is returned. + @param domain: the translation domain to retrieve. The 'Cthulhu' default should be used in most cases. + @returns: the gettext translation class. + """ + # localedir = os.path.join(self.path, "locale") + # return gettext.translation(domain, localedir=localedir, languages=[languageHandler.getLanguage()], fallback=True) +""" + def initTranslation(): + addon = getCodeAddon(frameDist=2) + translations = addon.getTranslationsInstance() + # Point _ to the translation object in the globals namespace of the caller frame + # FIXME: should we retrieve the caller module object explicitly? + try: + callerFrame = inspect.currentframe().f_back + callerFrame.f_globals['_'] = translations.gettext + # Install our pgettext function. + callerFrame.f_globals['pgettext'] = languageHandler.makePgettext(translations) + finally: + del callerFrame # Avoid reference problems with frames (per python docs) +""" + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/tutorialgenerator.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/tutorialgenerator.py new file mode 100644 index 0000000..8b18e50 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/tutorialgenerator.py @@ -0,0 +1,799 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Utilities for obtaining tutorial utterances for objects. In general, +there probably should be a singleton instance of the TutorialGenerator +class. For those wishing to override the generators, however, +one can create a new instance and replace/extend the tutorial generators +as they see fit.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2008-2009 Sun Microsystems Inc." +__license__ = "LGPL" + +import gi +gi.require_version("Atspi", "2.0") +from gi.repository import Atspi + +from . import debug +from . import cthulhu_state +from . import settings + +from .ax_object import AXObject +from .ax_utilities import AXUtilities +from .cthulhu_i18n import _ # for gettext support + +class TutorialGenerator: + """Takes accessible objects and produces a tutorial string to speak + for those objects. See the getTutorialString method, which is the + primary entry point. Subclasses can feel free to override/extend + the getTutorialGenerators instance field as they see fit.""" + + def __init__(self, script): + + # The script that created us. This allows us to ask the + # script for information if we need it. + # + self._script = script + # storing the last spoken message. + self.lastTutorial = "" + + self.lastRole = None + + # Set up a dictionary that maps role names to functions + # that generate tutorial strings for objects that implement that role. + # + self.tutorialGenerators = {} + self.tutorialGenerators[Atspi.Role.CHECK_BOX] = \ + self._getTutorialForCheckBox + self.tutorialGenerators[Atspi.Role.COMBO_BOX] = \ + self._getTutorialForComboBox + self.tutorialGenerators[Atspi.Role.FRAME] = \ + self._getTutorialForFrame + self.tutorialGenerators[Atspi.Role.ICON] = \ + self._getTutorialForIcon + self.tutorialGenerators[Atspi.Role.LAYERED_PANE] = \ + self._getTutorialForLayeredPane + self.tutorialGenerators[Atspi.Role.LIST] = \ + self._getTutorialForList + self.tutorialGenerators[Atspi.Role.LIST_ITEM] = \ + self._getTutorialForListItem + self.tutorialGenerators[Atspi.Role.PAGE_TAB] = \ + self._getTutorialForPageTab + self.tutorialGenerators[Atspi.Role.PARAGRAPH] = \ + self._getTutorialForText + self.tutorialGenerators[Atspi.Role.PASSWORD_TEXT] = \ + self._getTutorialForText + self.tutorialGenerators[Atspi.Role.ENTRY] = \ + self._getTutorialForText + self.tutorialGenerators[Atspi.Role.PUSH_BUTTON] = \ + self._getTutorialForPushButton + self.tutorialGenerators[Atspi.Role.SPIN_BUTTON] = \ + self._getTutorialForSpinButton + self.tutorialGenerators[Atspi.Role.TABLE_CELL] = \ + self._getTutorialForTableCellRow + self.tutorialGenerators[Atspi.Role.TEXT] = \ + self._getTutorialForText + self.tutorialGenerators[Atspi.Role.TOGGLE_BUTTON] = \ + self._getTutorialForCheckBox + self.tutorialGenerators[Atspi.Role.RADIO_BUTTON] = \ + self._getTutorialForRadioButton + self.tutorialGenerators[Atspi.Role.MENU] = \ + self._getTutorialForMenu + self.tutorialGenerators[Atspi.Role.CHECK_MENU_ITEM] = \ + self._getTutorialForCheckBox + self.tutorialGenerators[Atspi.Role.MENU_ITEM] = \ + self._getTutorialForMenuItem + self.tutorialGenerators[Atspi.Role.RADIO_MENU_ITEM] = \ + self._getTutorialForCheckBox + self.tutorialGenerators[Atspi.Role.SLIDER] = \ + self._getTutorialForSlider + + def _debugGenerator(self, generatorName, obj, alreadyFocused, utterances): + """Prints debug.LEVEL_FINER information regarding + the tutorial generator. + + Arguments: + - generatorName: the name of the generator + - obj: the object being presented + - alreadyFocused: False if object just received focus + - utterances: the generated text + """ + + debug.println(debug.LEVEL_FINER, + f"GENERATOR: {generatorName}") + debug.println(debug.LEVEL_FINER, + f" obj = {AXObject.get_name(obj)}") + debug.println(debug.LEVEL_FINER, + f" role = {AXObject.get_role_name(obj)}") + debug.println(debug.LEVEL_FINER, + f" alreadyFocused = {alreadyFocused}") + debug.println(debug.LEVEL_FINER, + " utterances:") + for text in utterances: + debug.println(debug.LEVEL_FINER, + f" ({text})") + + def _getDefaultTutorial( + self, obj, alreadyFocused, forceTutorial, role=None): + """The default tutorial generator returns the empty tutorial string + because We have no associated tutorial function for the object. + + Arguments: + - obj: an Accessible + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + - role: A role that should be used instead of the Accessible's + possible role. + + Returns the empty list [] + """ + + return [] + + + def _getTutorialForCheckBox(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a check box. + + Arguments: + - obj: the check box + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is a tip for the user on how to toggle a checkbox. + msg = _("Press space to toggle.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForCheckBox", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForComboBox(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a combobox. + + Arguments: + - obj: the combo box + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is a tip for the user on how to interact + # with a combobox. + msg = _("Press space to expand, and use up and down to select an item.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForComboBox", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForFrame(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a frame. + + Arguments: + - obj: the frame + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + + # Translators: If this application has more than one unfocused alert or + # dialog window, inform user of how to refocus these. + childWindowsMsg = _("Press alt+f6 to give focus to child windows.") + + # If this application has more than one unfocused alert or + # dialog window, tell user how to give them focus. + try: + alertAndDialogCount = \ + self._script.utilities.unfocusedAlertAndDialogCount(obj) + except Exception: + alertAndDialogCount = 0 + if alertAndDialogCount > 0: + utterances.append(childWindowsMsg) + + self._debugGenerator("_getTutorialForFrame", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForIcon(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for an icon. + + Arguments: + - obj: the icon + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + parent = AXObject.get_parent(obj) + if AXUtilities.is_layered_pane(parent): + utterances = self._getTutorialForLayeredPane(parent, + alreadyFocused, + forceTutorial) + else: + utterances = self._getDefaultTutorial(obj, + alreadyFocused, + forceTutorial) + + self._debugGenerator("_getTutorialForIcon", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForLayeredPane(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a layered pane. + + Arguments: + - obj: the layered pane + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + + # Translators: this gives tips on how to navigate items in a + # layered pane. + msg = _("To move to items, use either " \ + "the arrow keys or type ahead searching.") + utterances.append(msg) + + # Translators: this is the tutorial string for when first landing + # on the desktop, describing how to access the system menus. + desktopMsg = _("To get to the system menus press the alt+f1 key.") + + scriptName = self._script.name + sibling = AXObject.get_child(AXObject.get_parent(obj), 0) + if 'nautilus' in scriptName and obj == sibling: + utterances.append(desktopMsg) + + if (not alreadyFocused and self.lastTutorial != utterances) \ + or forceTutorial: + pass + else: + utterances = [] + + self._debugGenerator("_getTutorialForLayeredPane", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForList(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a list. + + Arguments: + - obj: the list + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + + # Translators: this is the tutorial string when navigating lists. + msg = _("Use up and down to select an item.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForList", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForListItem(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a listItem. + + Arguments: + - obj: the listitem + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + + # Translators: this represents the state of a node in a tree. + # 'expanded' means the children are showing. + # 'collapsed' means the children are not showing. + # this string informs the user how to collapse the node. + expandedMsg = _("To collapse, press shift plus left.") + + # Translators: this represents the state of a node in a tree. + # 'expanded' means the children are showing. + # 'collapsed' means the children are not showing. + # this string informs the user how to expand the node. + collapsedMsg = _("To expand, press shift plus right.") + + + # If already in focus then the tree probably collapsed or expanded + if AXUtilities.is_expandable(obj): + if AXUtilities.is_expanded(obj): + if (self.lastTutorial != [expandedMsg]) or forceTutorial: + utterances.append(expandedMsg) + else: + if (self.lastTutorial != [collapsedMsg]) or forceTutorial: + utterances.append(collapsedMsg) + + self._debugGenerator("_getTutorialForListItem", + obj, + alreadyFocused, + utterances) + return utterances + + def _getTutorialForMenuItem(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a menu item + + Arguments: + - obj: the menu item + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is the tutorial string for activating a menu item + msg = _("To activate press return.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForMenuItem", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForText(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a text object. + + Arguments: + - obj: the text component + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + if not AXUtilities.is_editable(obj): + return [] + + utterances = [] + # Translators: This is the tutorial string for when landing + # on text fields. + msg = _("Type in text.") + + if (not alreadyFocused or forceTutorial) and \ + not self._script.utilities.isReadOnlyTextArea(obj): + utterances.append(msg) + + self._debugGenerator("_getTutorialForText", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForPageTab(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a page tab. + + Arguments: + - obj: the page tab + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of tutorial utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is the tutorial string for landing + # on a page tab, we are informing the + # user how to navigate these. + msg = _("Use left and right to view other tabs.") + + if (self.lastTutorial != [msg]) or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForPageTabList", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForPushButton(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a push button + + Arguments: + - obj: the push button + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is the tutorial string for activating a push button. + msg = _("To activate press space.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForPushButton", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForSpinButton(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a spin button. If the object already has + focus, then no tutorial is given. + + Arguments: + - obj: the spin button + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is the tutorial string for when landing + # on a spin button. + msg = _("Use up or down arrow to select value." \ + " Or type in the desired numerical value.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForSpinButton", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForTableCell(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial utterances for a single table cell + + Arguments: + - obj: the table + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + + # Translators: this represents the state of a node in a tree. + # 'expanded' means the children are showing. + # 'collapsed' means the children are not showing. + # this string informs the user how to collapse the node. + expandedMsg = _("To collapse, press shift plus left.") + + # Translators: this represents the state of a node in a tree. + # 'expanded' means the children are showing. + # 'collapsed' means the children are not showing. + # this string informs the user how to expand the node. + collapsedMsg = _("To expand, press shift plus right.") + + # If this table cell has 2 children and one of them has a + # 'toggle' action and the other does not, then present this + # as a checkbox where: + # 1) we get the checked state from the cell with the 'toggle' action + # 2) we get the label from the other cell. + # See Cthulhu bug #376015 for more details. + # + if AXObject.get_child_count(obj) == 2: + cellOrder = [] + hasToggle = [ False, False ] + for i, child in enumerate(obj): + if self._script.utilities.hasMeaningfulToggleAction(child): + hasToggle[i] = True + break + if hasToggle[0] and not hasToggle[1]: + cellOrder = [ 1, 0 ] + elif not hasToggle[0] and hasToggle[1]: + cellOrder = [ 0, 1 ] + if cellOrder: + for i in cellOrder: + # Don't speak the label if just the checkbox state has + # changed. + # + if alreadyFocused and not hasToggle[i]: + pass + else: + utterances.extend( \ + self._getTutorialForTableCell(AXObject.get_child(obj, i), + alreadyFocused, forceTutorial)) + return utterances + + # [[[TODO: WDW - Attempt to infer the cell type. There's a + # bunch of stuff we can do here, such as check the EXPANDABLE + # state, check the NODE_CHILD_OF relation, etc. Logged as + # bugzilla bug 319750.]]] + # + if self._script.utilities.hasMeaningfulToggleAction(obj): + utterances = self._getTutorialForCheckBox( + obj, alreadyFocused, forceTutorial) + + if AXUtilities.is_expandable(obj): + if AXUtilities.is_expanded(obj): + if self.lastTutorial != [expandedMsg] or forceTutorial: + utterances.append(expandedMsg) + else: + if self.lastTutorial != [collapsedMsg] or forceTutorial: + utterances.append(collapsedMsg) + + self._debugGenerator("_getTutorialForTableCell", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForTableCellRow(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for the active table cell in the table row. + + Arguments: + - obj: the table + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + + if (not alreadyFocused): + parent = AXObject.get_parent(obj) + try: + parent_table = parent.queryTable() + except Exception: + parent_table = None + readFullRow = self._script.utilities.shouldReadFullRow(obj) + if readFullRow and parent_table and not self._script.utilities.isLayoutOnly(parent): + utterances.extend(self._getTutorialForTableCell(obj, + alreadyFocused, forceTutorial)) + else: + utterances = self._getTutorialForTableCell(obj, alreadyFocused, forceTutorial) + else: + utterances = self._getTutorialForTableCell(obj, alreadyFocused, \ + forceTutorial) + + self._debugGenerator("_getTutorialForTableCellRow", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getTutorialForRadioButton(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a radio button. + + Arguments: + - obj: the radio button + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is a tip for the user, how to navigate radiobuttons. + msg = _("Use arrow keys to change.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForRadioButton", + obj, + alreadyFocused, + utterances) + return utterances + + def _getTutorialForMenu(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a menu. + + Arguments: + - obj: the menu + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is a tip for the user, how to navigate menus. + mainMenuMsg = _("To navigate, press left or right arrow. " \ + "To move through items press up or down arrow.") + + # Translators: this is a tip for the user, how to + # navigate into sub menus. + subMenuMsg = _("To enter sub menu, press right arrow.") + + # Checking if we are a submenu, + # we can't rely on our parent being just a menu. + # TODO - JD: What exactly are the __class__ checks for? All accessible objects + # have the same class. Should this be checking the role instead? + parent = AXObject.get_parent(obj) + if AXObject.get_name(parent) and parent.__class__ == obj.__class__: + if (self.lastTutorial != [subMenuMsg]) or forceTutorial: + utterances.append(subMenuMsg) + else: + if (self.lastTutorial != [mainMenuMsg]) or forceTutorial: + utterances.append(mainMenuMsg) + + self._debugGenerator("_getTutorialForMenu", + obj, + alreadyFocused, + utterances) + return utterances + + def _getTutorialForSlider(self, obj, alreadyFocused, forceTutorial): + """Get the tutorial string for a slider. If the object already has + focus, then no tutorial is given. + + Arguments: + - obj: the slider + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + + Returns a list of utterances to be spoken for the object. + """ + + utterances = [] + # Translators: this is the tutorial string for when landing + # on a slider. + msg = _("To decrease press left arrow, to increase press right arrow." \ + " To go to minimum press home, and for maximum press end.") + + if (not alreadyFocused and self.lastTutorial != [msg]) \ + or forceTutorial: + utterances.append(msg) + + self._debugGenerator("_getTutorialForSlider", + obj, + alreadyFocused, + utterances) + + return utterances + + def _getBindingsForHandler(self, handlerName): + handler = self._script.inputEventHandlers.get(handlerName) + if not handler: + return None + + bindings = self._script.keyBindings.getBindingsForHandler(handler) + if not bindings: + return None + + binding = bindings[0] + return binding.asString() + + def _getModeTutorial(self, obj, alreadyFocused, forceTutorial): + return [] + + def getTutorial(self, obj, alreadyFocused, forceTutorial=False, role=None): + """Get the tutorial for an Accessible object. This will look + first to the specific tutorial generators and if this + does not exist then return the empty tutorial. + This method is the primary method + that external callers of this class should use. + + Arguments: + - obj: the object + - alreadyFocused: False if object just received focus + - forceTutorial: used for when whereAmI really needs the tutorial string + - role: Alternative role to use + + Returns a list of utterances to be spoken. + """ + + if not settings.enableTutorialMessages: + return [] + + if not (obj and obj == cthulhu_state.locusOfFocus): + return [] + + # Widgets in document content don't necessarily have the same interaction + # as native toolkits. Because we can't know for certain what a keystroke + # will do, better to say nothing than to risk confusing the user with + # bogus info. + if self._script.utilities.inDocumentContent(obj): + tokens = ["INFO: Not generating tutorial for document object", obj, "."] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return [] + + utterances = [] + role = role or AXObject.get_role(obj) + msg = self._getModeTutorial(obj, alreadyFocused, forceTutorial) + if not msg: + if role in self.tutorialGenerators: + generator = self.tutorialGenerators[role] + else: + generator = self._getDefaultTutorial + msg = generator(obj, alreadyFocused, forceTutorial) + if msg == self.lastTutorial and role == self.lastRole \ + and not forceTutorial: + msg = [] + if msg: + utterances = [" ".join(msg)] + self.lastTutorial = msg + self.lastRole = role + if forceTutorial: + self.lastTutorial = "" + self.lastRole = None + + self._debugGenerator("getTutorial", + obj, + alreadyFocused, + utterances) + return utterances diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/where_am_i_presenter.py b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/where_am_i_presenter.py new file mode 100644 index 0000000..bbcac10 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/lib/python3.13/site-packages/cthulhu/where_am_i_presenter.py @@ -0,0 +1,496 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Stormux +# Copyright (c) 2010-2012 The Orca Team +# Copyright (c) 2012 Igalia, S.L. +# Copyright (c) 2005-2010 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. +# +# Fork of Orca Screen Reader (GNOME) +# Original source: https://gitlab.gnome.org/GNOME/orca + +"""Module for commands related to the current accessible object.""" + +__id__ = "$Id$" +__version__ = "$Revision$" +__date__ = "$Date$" +__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \ + "Copyright (c) 2016-2023 Igalia, S.L." +__license__ = "LGPL" + +from . import cmdnames +from . import debug +from . import input_event +from . import keybindings +from . import messages +from . import cthulhu_state +from . import settings_manager +from .ax_object import AXObject +from .ax_utilities import AXUtilities + +_settingsManager = settings_manager.getManager() + +class WhereAmIPresenter: + """Module for commands related to the current accessible object.""" + + def __init__(self): + self._handlers = self._setup_handlers() + self._desktop_bindings = self._setup_desktop_bindings() + self._laptop_bindings = self._setup_laptop_bindings() + + def get_bindings(self, is_desktop): + """Returns the where-am-i-presenter keybindings.""" + + if is_desktop: + return self._desktop_bindings + return self._laptop_bindings + + def get_handlers(self): + """Returns the where-am-i-presenter handlers.""" + + return self._handlers + + def _setup_handlers(self): + """Sets up and returns the where-am-i-presenter input event handlers.""" + + handlers = {} + + handlers["readCharAttributesHandler"] = \ + input_event.InputEventHandler( + self.present_character_attributes, + cmdnames.READ_CHAR_ATTRIBUTES) + + handlers["presentSizeAndPositionHandler"] = \ + input_event.InputEventHandler( + self.present_size_and_position, + cmdnames.PRESENT_SIZE_AND_POSITION) + + handlers["getTitleHandler"] = \ + input_event.InputEventHandler( + self.present_title, + cmdnames.PRESENT_TITLE) + + handlers["getStatusBarHandler"] = \ + input_event.InputEventHandler( + self.present_status_bar, + cmdnames.PRESENT_STATUS_BAR) + + handlers["present_default_button"] = \ + input_event.InputEventHandler( + self.present_default_button, + cmdnames.PRESENT_DEFAULT_BUTTON) + + handlers["whereAmIBasicHandler"] = \ + input_event.InputEventHandler( + self.where_am_i_basic, + cmdnames.WHERE_AM_I_BASIC) + + handlers["whereAmIDetailedHandler"] = \ + input_event.InputEventHandler( + self.where_am_i_detailed, + cmdnames.WHERE_AM_I_DETAILED) + + handlers["whereAmILinkHandler"] = \ + input_event.InputEventHandler( + self.present_link, + cmdnames.WHERE_AM_I_LINK) + + handlers["whereAmISelectionHandler"] = \ + input_event.InputEventHandler( + self.present_selection, + cmdnames.WHERE_AM_I_SELECTION) + + return handlers + + def _setup_desktop_bindings(self): + """Sets up and returns the where-am-i-presenter desktop key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "f", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("readCharAttributesHandler"))) + + bindings.add( + keybindings.KeyBinding( + "e", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("present_default_button"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("presentSizeAndPositionHandler"))) + + bindings.add( + keybindings.KeyBinding( + "KP_Enter", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("getTitleHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "KP_Enter", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("getStatusBarHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "KP_Enter", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("whereAmIBasicHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "KP_Enter", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("whereAmIDetailedHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("whereAmILinkHandler"))) + + bindings.add( + keybindings.KeyBinding( + "Up", + keybindings.defaultModifierMask, + keybindings.CTHULHU_SHIFT_MODIFIER_MASK, + self._handlers.get("whereAmISelectionHandler"))) + + return bindings + + def _setup_laptop_bindings(self): + """Sets up and returns the where-am-i-presenter laptop key bindings.""" + + bindings = keybindings.KeyBindings() + + bindings.add( + keybindings.KeyBinding( + "f", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("readCharAttributesHandler"))) + + bindings.add( + keybindings.KeyBinding( + "e", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("present_default_button"))) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("presentSizeAndPositionHandler"))) + + bindings.add( + keybindings.KeyBinding( + "slash", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("getTitleHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "slash", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("getStatusBarHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "Return", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("whereAmIBasicHandler"), + 1)) + + bindings.add( + keybindings.KeyBinding( + "Return", + keybindings.defaultModifierMask, + keybindings.CTHULHU_MODIFIER_MASK, + self._handlers.get("whereAmIDetailedHandler"), + 2)) + + bindings.add( + keybindings.KeyBinding( + "", + keybindings.defaultModifierMask, + keybindings.NO_MODIFIER_MASK, + self._handlers.get("whereAmILinkHandler"))) + + bindings.add( + keybindings.KeyBinding( + "Up", + keybindings.defaultModifierMask, + keybindings.CTHULHU_SHIFT_MODIFIER_MASK, + self._handlers.get("whereAmISelectionHandler"))) + + return bindings + + def present_character_attributes(self, script, event=None): + """Presents the font and formatting details for the current character.""" + + attrs = script.utilities.textAttributes(cthulhu_state.locusOfFocus, None, True)[0] + + # Get a dictionary of text attributes that the user cares about. + [user_attr_list, user_attr_dict] = script.utilities.stringToKeysAndDict( + _settingsManager.getSetting('enabledSpokenTextAttributes')) + + null_values = ['0', '0mm', 'none', 'false'] + for key in user_attr_list: + # Convert the standard key into the non-standard implementor variant. + app_key = script.utilities.getAppNameForAttribute(key) + value = attrs.get(app_key) + ignore_if_value = user_attr_dict.get(key) + if value in null_values and ignore_if_value in null_values: + continue + + if value and value != ignore_if_value: + script.speakMessage(script.utilities.localizeTextAttribute(key, value)) + + return True + + def present_size_and_position(self, script, event=None): + """Presents the size and position of the current object.""" + + if script.flatReviewPresenter.is_active(): + obj = script.flatReviewPresenter.get_current_object(script, event) + else: + obj = cthulhu_state.locusOfFocus + + x_coord, y_coord, width, height = script.utilities.getBoundingBox(obj) + if (x_coord, y_coord, width, height) == (-1, -1, 0, 0): + full = messages.LOCATION_NOT_FOUND_FULL + brief = messages.LOCATION_NOT_FOUND_BRIEF + script.presentMessage(full, brief) + return True + + full = messages.SIZE_AND_POSITION_FULL % (width, height, x_coord, y_coord) + brief = messages.SIZE_AND_POSITION_BRIEF % (width, height, x_coord, y_coord) + script.presentMessage(full, brief) + return True + + def present_title(self, script, event=None): + """Presents the title of the current window.""" + + obj = cthulhu_state.locusOfFocus + if AXObject.is_dead(obj): + obj = cthulhu_state.activeWindow + + if obj is None or AXObject.is_dead(obj): + script.presentMessage(messages.LOCATION_NOT_FOUND_FULL) + return True + + title = script.speechGenerator.generateTitle(obj) + for (string, voice) in title: + script.presentMessage(string, voice=voice) + return True + + def _present_default_button(self, script, event=None, dialog=None, error_messages=True): + """Presents the default button of the current dialog.""" + + obj = cthulhu_state.locusOfFocus + frame, dialog = script.utilities.frameAndDialog(obj) + if dialog is None: + if error_messages: + script.presentMessage(messages.DIALOG_NOT_IN_A) + return True + + button = AXUtilities.get_default_button(dialog) + if button is None: + if error_messages: + script.presentMessage(messages.DEFAULT_BUTTON_NOT_FOUND) + return True + + name = AXObject.get_name(button) + if not AXUtilities.is_sensitive(button): + script.presentMessage(messages.DEFAULT_BUTTON_IS_GRAYED % name) + return True + + script.presentMessage(messages.DEFAULT_BUTTON_IS % name) + return True + + def present_status_bar(self, script, event=None): + """Presents the status bar of the current window.""" + + obj = cthulhu_state.locusOfFocus + frame, dialog = script.utilities.frameAndDialog(obj) + if frame: + statusbar = AXUtilities.get_status_bar(frame) + if statusbar: + script.pointOfReference['statusBarItems'] = None + script.presentObject(statusbar, interrupt=True) + script.pointOfReference['statusBarItems'] = None + else: + full = messages.STATUS_BAR_NOT_FOUND_FULL + brief = messages.STATUS_BAR_NOT_FOUND_BRIEF + script.presentMessage(full, brief) + + infobar = script.utilities.infoBar(frame) + if infobar: + script.presentObject(infobar, interrupt=statusbar is None) + + # TODO - JD: Pending user feedback, this should be removed. + if dialog: + self._present_default_button(script, event, dialog, False) + + return True + + def present_default_button(self, script, event=None): + """Presents the default button of the current window.""" + + return self._present_default_button(script, event) + + def present_link(self, script, event=None, link=None): + """Presents details about the current link.""" + + link = link or cthulhu_state.locusOfFocus + if not script.utilities.isLink(link): + script.presentMessage(messages.NOT_ON_A_LINK) + return True + + return self._do_where_am_i(script, event, True, link) + + def present_selected_text(self, script, event=None, obj=None): + """Presents the selected text.""" + + obj = obj or cthulhu_state.locusOfFocus + if obj is None: + script.speakMessage(messages.LOCATION_NOT_FOUND_FULL) + return True + + text = script.utilities.allSelectedText(obj)[0] + if not text: + script.speakMessage(messages.NO_SELECTED_TEXT) + return True + + if script.utilities.shouldVerbalizeAllPunctuation(obj): + text = script.utilities.verbalizeAllPunctuation(text) + + msg = messages.SELECTED_TEXT_IS % text + script.speakMessage(msg) + return True + + def present_selection(self, script, event=None, obj=None): + """Presents the selected text or selected objects.""" + + obj = obj or cthulhu_state.locusOfFocus + if obj is None: + script.speakMessage(messages.LOCATION_NOT_FOUND_FULL) + return True + + tokens = ["WHERE AM I PRESENTER: presenting selection for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + + spreadsheet = AXObject.find_ancestor(obj, script.utilities.isSpreadSheetTable) + if spreadsheet is not None and script.utilities.speakSelectedCellRange(spreadsheet): + return True + + container = script.utilities.getSelectionContainer(obj) + if container is None: + tokens = ["WHERE AM I PRESENTER: Selection container not found for", obj] + debug.printTokens(debug.LEVEL_INFO, tokens, True) + return self.present_selected_text(script, event, obj) + + selected_count = script.utilities.selectedChildCount(container) + child_count = script.utilities.selectableChildCount(container) + script.presentMessage(messages.selectedItemsCount(selected_count, child_count)) + if not selected_count: + return True + + selected_items = script.utilities.selectedChildren(container) + item_names = ",".join(map(AXObject.get_name, selected_items)) + script.speakMessage(item_names) + return True + + def _do_where_am_i(self, script, event=None, basic_only=True, obj=None): + """Presents details about the current location at the specified level.""" + + if script.spellcheck and script.spellcheck.isActive(): + script.spellcheck.presentErrorDetails(not basic_only) + + if obj is None: + obj = cthulhu_state.locusOfFocus + if AXObject.is_dead(obj): + obj = cthulhu_state.activeWindow + + if obj is None or AXObject.is_dead(obj): + script.presentMessage(messages.LOCATION_NOT_FOUND_FULL) + return True + + if basic_only: + format_type = 'basicWhereAmI' + else: + format_type = 'detailedWhereAmI' + + script.presentObject( + script.utilities.realActiveAncestor(obj), + alreadyFocused=True, + formatType=format_type, + forceMnemonic=True, + forceList=True, + forceTutorial=True, + speechOnly=True) + + return True + + def where_am_i_basic(self, script, event=None): + """Presents basic information about the current location.""" + + return self._do_where_am_i(script, event) + + def where_am_i_detailed(self, script, event=None): + """Presents detailed information about the current location.""" + + # TODO - JD: For some reason, we are starting the basic where am I + # in response to the first click. Then we do the detailed one in + # response to the second click. Until that's fixed, interrupt the + # first one. + script.presentationInterrupt() + return self._do_where_am_i(script, event, False) + +_presenter = None +def getPresenter(): + """Returns the Where Am I Presenter""" + + global _presenter + if _presenter is None: + _presenter = WhereAmIPresenter() + return _presenter diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/icons/cthulhu-splash.svg b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/icons/cthulhu-splash.svg new file mode 100644 index 0000000..25dbb32 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/icons/cthulhu-splash.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-find.ui b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-find.ui new file mode 100644 index 0000000..b24158d --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-find.ui @@ -0,0 +1,359 @@ + + + + + False + 12 + Find + False + True + dialog + + + Screen Reader Find Dialog + + + + + + True + False + vertical + + + True + False + end + + + _Close + True + True + True + False + True + + + + False + True + 0 + + + + + _Find + True + False + True + True + True + False + True + + + + False + True + 1 + + + + + False + True + end + 0 + + + + + True + False + 20 + 20 + + + True + False + 5 + + + True + False + 0 + _Search for: + True + True + searchForEntry + 12 + + + Search for: + + + + + 0 + 0 + + + + + True + True + True + + True + + + Search for: + + + + + + 1 + 0 + 2 + + + + + 0 + 0 + + + + + True + False + end + 20 + 20 + + + True + False + 0 + none + + + True + False + + + True + False + + + C_urrent location + True + True + False + True + True + True + + + + 0 + 0 + + + + + _Top of window + True + True + False + True + True + currentLocationRadioButton + + + Top of window + + + + + + 0 + 1 + + + + + + + + + True + False + Start from: + + + Start from: + + + + + + + + + + 0 + 0 + + + + + True + False + 0 + none + + + True + False + + + True + False + + + _Wrap around + True + True + False + True + True + True + + + + 0 + 1 + + + + + Search _backwards + True + True + False + True + True + + + + 0 + 0 + + + + + + + + + True + False + Search direction: + + + + + + + + 1 + 0 + + + + + True + False + 0 + none + + + True + False + + + True + False + + + _Match case + True + True + False + True + True + + + + 0 + 0 + + + + + Match _entire word only + True + True + False + True + True + + + + 0 + 1 + + + + + + + + + True + False + Options: + + + + + + + + 2 + 0 + + + + + 0 + 1 + + + + + True + True + 1 + + + + + + closeButton + findButton + + + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-setup.ui b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-setup.ui new file mode 100644 index 0000000..e275007 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/cthulhu/ui/cthulhu-setup.ui @@ -0,0 +1,3667 @@ + + + + + 9999 + 10 + 1 + 10 + + + + + + + + + + + + + + + + + + + + + Default + + + Uppercase + + + Hyperlink + + + System + + + + + + + + + + + Line + + + Sentence + + + + + + + + + + + All + + + Application + + + Window + + + + + + + + + + + Insert, KP_Insert + + + KP_Insert + + + Insert + + + Caps_Lock, Shift_Lock + + + + + + + + + + + + + 10 + 5 + 0.10000000149 + 1 + + + 9999 + 10 + 1 + 10 + + + 100 + 50 + 1 + 10 + + + 10 + 10 + 0.10000000149 + 1 + + + False + Cthulhu Preferences + normal + + + + + True + False + vertical + 3 + + + True + False + end + + + _Help + True + True + True + False + True + + + + False + False + 0 + + + + + _Apply + True + True + True + False + True + + + + False + False + 1 + + + + + _Cancel + True + True + True + False + True + + + + False + False + 2 + + + + + _OK + True + True + True + False + True + + + + False + False + 3 + + + + + False + True + end + 0 + + + + + True + True + + + True + False + 12 + 10 + 10 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + _Desktop + True + True + False + True + True + True + + + + 0 + 0 + + + + + _Laptop + True + True + False + True + True + generalDesktopButton + + + + 0 + 1 + + + + + + + + + True + False + Keyboard Layout + + + + + + + + 0 + 0 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + True + + + 150 + True + False + 0 + Active _Profile: + True + availableProfilesComboBox1 + + + + + + 0 + 0 + + + + + True + False + 0 + Start-up Profile: + availableProfilesComboBox2 + + + + + + 0 + 1 + + + + + 200 + True + False + model9 + + + + 0 + + + + + 1 + 0 + + + + + True + False + model9 + + + + 0 + + + + + 1 + 1 + + + + + _Load + True + True + True + True + + + + 2 + 0 + + + + + Save _As + True + True + True + True + + + + 3 + 0 + + + + + _Remove + True + True + True + True + + + + 4 + 0 + + + + + + + + + + + + + + + + + + True + False + Profiles + + + + + + + + 0 + 3 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + _Present tooltips + True + True + False + True + 0 + True + + + + 0 + 0 + + + + + Speak object under mo_use + True + True + False + True + 0 + True + True + + + + 0 + 1 + + + + + + + + + True + False + Mouse + + + + + + + + 0 + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + True + + + 150 + True + False + 0 + _Time format: + True + timeFormatCombo + + + + + + 0 + 0 + + + + + True + False + 0 + Dat_e format: + True + dateFormatCombo + + + + + + 0 + 1 + + + + + True + False + liststore1 + + + + + 0 + + + + + 1 + 0 + + + + + True + False + liststore2 + + + + + 0 + + + + + 1 + 1 + + + + + + + + + True + False + Time and Date + + + + + + + + 0 + 2 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + _Speak updates + True + True + False + start + True + True + 0 + True + True + + + + 0 + 0 + + + + + _Braille updates + True + True + False + True + True + True + + + + 0 + 1 + + + + + True + False + 10 + 20 + + + True + True + + 10 + progressBarUpdateIntervalAdjustment + 1 + True + 10 + + + + 1 + 0 + + + + + True + False + Frequency (secs): + True + progressBarUpdateIntervalSpinButton + 0 + + + 0 + 0 + + + + + True + False + Applies to: + True + progressBarVerbosity + 0 + + + 0 + 1 + + + + + True + False + model7 + + + + + 0 + + + + + 1 + 1 + + + + + 0 + 3 + + + + + Bee_p updates + True + True + False + start + True + True + 0 + True + True + + + + 0 + 2 + + + + + + + + + True + False + Progress Bar Updates + + + + + + + + 1 + 0 + 2 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Enable _rewind and fast forward in Say All + True + True + False + True + 0 + True + + + + 0 + 0 + + + + + Enable _structural navigation in Say All + True + True + False + True + 0 + True + True + + + + 0 + 1 + + + + + True + False + 20 + 20 + + + -` + True + False + Say All B_y: + True + sayAllStyle + 0 + + + + + + 0 + 0 + + + + + True + False + model2 + + + + + 0 + + + + + 1 + 0 + + + + + 0 + 8 + + + + + Announce block_quotes in Say All + True + True + False + True + 0 + True + True + + + + 0 + 2 + + + + + Announce li_sts in Say All + True + True + False + True + 0 + True + True + + + + 0 + 5 + + + + + Announce _tables in Say All + True + True + False + True + 0 + True + True + + + + 0 + 7 + + + + + Announce _panels in Say All + True + True + False + True + 0 + True + True + + + + 0 + 6 + + + + + Announce _forms in Say All + True + True + False + True + 0 + True + True + + + + 0 + 3 + + + + + Announce land_marks in Say All + True + True + False + True + 0 + True + True + + + + 0 + 4 + + + + + + + + + True + False + Say All + + + + + + + + 1 + 2 + 2 + + + + + + + True + False + General + + + False + + + + + True + False + 12 + 10 + 40 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 12 + + + True + False + 1 + Vo_lume: + True + right + volumeScale + + + + + + 0 + 8 + + + + + True + True + volumeAdjustment + 1 + right + + + + + 1 + 8 + + + + + True + True + pitchAdjustment + 1 + right + + + + + 1 + 7 + + + + + True + False + 1 + Pi_tch: + True + right + pitchScale + + + 0 + 7 + + + + + True + True + rateAdjustment + 0 + 0 + right + + + + + 1 + 6 + + + + + True + False + 1 + _Rate: + True + right + rateScale + + + 0 + 6 + + + + + True + False + + + + 1 + 4 + + + + + True + False + 1 + _Person: + True + right + speechFamilies + + + 0 + 4 + + + + + True + False + + + + 1 + 3 + + + + + True + False + 1 + _Language: + True + right + speechLanguages + + + 0 + 3 + + + + + True + False + + + + 1 + 2 + + + + + True + False + 1 + Speech synthesi_zer: + True + right + speechServers + + + 0 + 2 + + + + + True + False + + + + 1 + 1 + + + + + True + False + 1 + Speech _system: + True + right + speechSystems + + + 0 + 1 + + + + + True + False + model1 + + + + + 0 + + + + + 1 + 0 + + + + + True + False + 1 + _Voice type: + True + right + voiceTypesCombo + + + 0 + 0 + + + + + True + False + _Capitalization style: + True + right + capitalizationStyle + 1 + + + 0 + 5 + + + + + True + False + + + + + 0 + + + + + 1 + 5 + + + + + + + + + True + False + Voice Type Settings + + + + + + + + 0 + 0 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Break speech into ch_unks between pauses + True + True + False + True + True + True + + + + 0 + 0 + + + + + Speak multicase strings as wor_ds + True + True + False + True + True + True + + + + 0 + 1 + + + + + Speak _numbers as digits + True + True + False + True + True + True + + + + 0 + 2 + + + + + + + + + + + + True + False + Global Voice Settings + + + + + + + + 1 + 0 + + + + + 1 + + + + + True + False + Voice + + + 1 + False + + + + + True + False + 12 + 10 + 10 + + + _Enable speech + True + True + False + True + True + True + + + + 0 + 0 + + + + + True + False + vertical + 50 + 20 + + + True + False + 20 + 20 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Brie_f + True + True + False + True + True + True + + + + 0 + 0 + + + + + Ver_bose + True + True + False + True + True + speechBriefButton + + + + 0 + 1 + + + + + + + + + True + False + Verbosity + + + + + + + + 0 + 0 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + _None + True + True + False + True + True + True + + + + 0 + 0 + + + + + So_me + True + True + False + True + True + noneButton + + + + 0 + 1 + + + + + M_ost + True + True + False + True + True + noneButton + + + + 0 + 2 + + + + + _All + True + True + False + True + True + noneButton + + + + 0 + 3 + + + + + + + + + True + False + Punctuation Level + + + + + + + + 0 + 1 + + + + + 0 + 0 + + + + + True + False + 20 + 10 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Only speak displayed text + True + True + False + True + True + True + + + + 0 + 0 + + + + + True + False + + + Speak blank lines + True + True + False + True + True + True + + + + 0 + 0 + + + + + Speak _indentation and justification + True + True + False + True + True + + + + 0 + 1 + + + + + Spea_k object mnemonics + True + True + False + True + True + True + + + + 0 + 3 + + + + + Speak child p_osition + True + True + False + True + True + True + + + + 0 + 4 + + + + + Speak tutorial messages + True + True + False + True + True + True + + + + 0 + 5 + + + + + _System messages are detailed + True + True + False + True + 0 + True + True + + + + 0 + 7 + + + + + S_peak colors as names + True + True + False + True + 0 + True + True + + + + 0 + 8 + + + + + Announce block_quotes during navigation + True + True + False + True + 0 + True + True + + + + 0 + 9 + + + + + Announce _lists during navigation + True + True + False + True + 0 + True + True + + + + 0 + 12 + + + + + Announce _tables during navigation + True + True + False + True + 0 + True + True + + + + 0 + 14 + + + + + Speak _misspelled-word indicator + True + True + False + True + 0 + True + True + + + + 0 + 2 + + + + + Announce _panels during navigation + True + True + False + True + 0 + True + True + + + + 0 + 13 + + + + + Announce land_marks during navigation + True + True + False + True + 0 + True + True + + + + 0 + 11 + + + + + Announce _forms during navigation + True + True + False + True + 0 + True + True + + + + 0 + 10 + + + + + Speak _description + True + True + False + True + 0 + True + True + + + + 0 + 6 + + + + + 0 + 1 + + + + + Speak full row in sp_readsheets + True + True + False + True + 0 + True + True + + + + 0 + 4 + + + + + Speak full row in _document tables + True + True + False + True + 0 + True + True + + + + 0 + 3 + + + + + Speak full row in _GUI tables + True + True + False + True + 0 + True + True + + + + 0 + 2 + + + + + + + + + True + False + Spoken Context + + + + + + + + 0 + 0 + + + + + + + + 1 + 0 + + + + + 0 + 1 + + + + + 2 + + + + + True + False + Speech + + + 2 + False + + + + + True + False + 12 + 10 + 10 + + + True + False + + + Enable Braille _support + True + True + False + True + True + True + + + + 0 + 0 + + + + + 0 + 0 + + + + + True + False + 10 + 10 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + _Abbreviated role names + True + True + False + True + True + + + + 0 + 1 + + + + + Disable _end of line symbol + True + True + False + True + True + + + + 0 + 0 + + + + + True + False + 20 + 20 + + + True + False + 0.40999999642372131 + Contraction _Table: + True + contractionTableCombo + + + + + + 0 + 0 + + + + + True + False + + + + 1 + 0 + + + + + 0 + 4 + + + + + _Enable Contracted Braille + True + True + False + True + True + + + + 0 + 3 + + + + + Enable _word wrap + True + True + False + True + True + + + + 0 + 2 + + + + + + + + + True + False + Display Settings + + + + + + + + 0 + 0 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Brie_f + True + True + False + True + True + True + + + + 0 + 0 + + + + + Ver_bose + True + True + False + True + True + brailleBriefButton + + + + 0 + 1 + + + + + + + + + True + False + Verbosity + + + + + + + + 0 + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 20 + + + _None + True + True + False + True + True + True + + + + 0 + 0 + + + + + Dot _7 + True + True + False + True + True + brailleSelectionNoneButton + + + + 0 + 1 + + + + + Dot _8 + True + True + False + True + True + brailleSelectionNoneButton + + + + 1 + 0 + + + + + Dots 7 an_d 8 + True + True + False + True + True + brailleSelectionNoneButton + + + + 1 + 1 + + + + + + + + + True + False + Selection Indicator + + + + + + + + 0 + 2 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 20 + + + _None + True + True + False + True + True + True + + + + 0 + 0 + + + + + Dot _7 + True + True + False + True + True + brailleLinkNoneButton + + + + 0 + 1 + + + + + Dot _8 + True + True + False + True + True + brailleLinkNoneButton + + + + 1 + 0 + + + + + Dots 7 an_d 8 + True + True + False + True + True + brailleLinkNoneButton + + + + 1 + 1 + + + + + + + + + True + False + Hyperlink Indicator + + + + + + + + 0 + 3 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Enable flash _messages + True + True + False + True + 0 + True + True + + + + 0 + 0 + + + + + True + False + + + True + False + D_uration (secs): + True + brailleFlashTimeSpinButton + 0 + + + 0 + 0 + + + + + True + True + + brailleFlashTimeAdjustment + 1 + True + 5 + + + + 1 + 0 + + + + + 0 + 3 + + + + + Messages are _persistent + True + True + False + True + 0 + True + True + + + + 0 + 2 + + + + + Messages are _detailed + True + True + False + True + 0 + True + True + + + + 0 + 1 + + + + + + + + + True + False + Flash Message Settings + end + + + + + + + + 1 + 0 + + + + + + + + + + + + + + 0 + 1 + + + + + 3 + + + + + True + False + Braille + + + 3 + False + + + + + True + False + 12 + + + Enable _key echo + True + True + False + True + True + + + + 0 + 0 + + + + + True + False + 25 + + + True + False + + + Enable _alphabetic keys + True + True + False + True + True + + + + 0 + 0 + + + + + Enable n_umeric keys + True + True + False + True + True + + + + 0 + 1 + + + + + Enable _punctuation keys + True + True + False + True + True + + + + 0 + 2 + + + + + Enable _space + True + True + False + True + True + + + + 0 + 3 + + + + + Enable _modifier keys + True + True + False + True + True + + + + 0 + 4 + + + + + Enable _function keys + True + True + False + True + True + + + + 0 + 5 + + + + + Enable ac_tion keys + True + True + False + True + True + + + + 0 + 6 + + + + + Enable _navigation keys + True + True + False + True + True + + + + 0 + 7 + + + + + Enable non-spacing _diacritical keys + True + True + False + True + True + + + + 0 + 8 + + + + + + + + + + 0 + 1 + + + + + Enable echo by cha_racter + True + True + False + True + True + + + + 0 + 2 + + + + + Enable echo by _word + True + True + False + True + True + + + + 0 + 3 + + + + + Enable echo by _sentence + True + True + False + True + True + + + + 0 + 4 + + + + + 4 + + + + + True + False + Echo + + + 4 + False + + + + + True + False + 12 + 10 + 10 + + + True + False + 10 + 10 + + + True + False + Screen Reader _Modifier Key(s): + True + cthulhuModifierComboBox + + + + + + 0 + 0 + + + + + True + False + model8 + + + + + 0 + + + + + 1 + 0 + + + + + 0 + 0 + + + + + True + True + True + True + in + + + True + True + True + + + + + + + + 0 + 1 + + + + + 5 + + + + + True + False + Key Bindings + + + 5 + False + + + + + True + False + + + True + False + True + True + 5 + 0 + none + + + True + False + 12 + + + True + True + 5 + in + + + True + True + True + + + + + + + + + + + + True + False + Pronunciation Dictionary + + + + + + + + 0 + 0 + + + + + True + False + + + _New entry + True + True + True + 5 + True + + + + 0 + 0 + + + + + _Delete + True + True + True + 5 + True + + + + 1 + 0 + + + + + 0 + 1 + + + + + 6 + + + + + True + False + Pronunciation + + + 6 + False + + + + + True + False + True + True + + + True + False + True + True + 5 + 0 + none + + + True + False + 12 + + + True + False + True + True + + + True + False + + + _Speak all + True + True + 5 + True + + + + 0 + 0 + + + + + Speak _none + True + True + 5 + True + + + + 1 + 0 + + + + + _Reset + True + True + True + 5 + True + + + + 2 + 0 + + + + + 0 + 1 + + + + + True + True + True + True + 5 + in + + + True + True + True + + + + + + + + 0 + 0 + + + + + + + + + True + False + Text attributes + + + + + + + + 0 + 0 + + + + + True + False + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + + + Move to _bottom + True + True + True + 5 + True + + + + 0 + 3 + + + + + Move _down one + True + True + True + 5 + True + + + + 0 + 2 + + + + + Move _up one + True + True + True + 5 + True + + + + 0 + 1 + + + + + Move to _top + True + True + True + 5 + True + + + + 0 + 0 + + + + + + + + + True + False + Adjust selected attribute + + + + + + + + 0 + 0 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + + + _None + True + True + False + True + True + True + + + + 0 + 0 + + + + + Dot _7 + True + True + False + True + True + textBrailleNoneButton + + + + 0 + 1 + + + + + Dot _8 + True + True + False + True + True + textBrailleNoneButton + + + + 0 + 2 + + + + + Dots 7 an_d 8 + True + True + False + True + True + textBrailleNoneButton + + + + 0 + 3 + + + + + + + + + True + False + Braille Indicator + + + + + + + + 0 + 1 + + + + + 1 + 0 + + + + + 7 + + + + + True + False + Text Attributes + + + 7 + False + + + + + True + False + 12 + 12 + 12 + 12 + 6 + 12 + + + Enable AI Assistant + True + True + False + True + True + + + + 0 + 0 + 2 + + + + + True + False + start + _Provider: + True + aiProviderCombo + + + 0 + 1 + + + + + True + False + True + + Claude Code (Enhanced) + Claude (Anthropic) + ChatGPT (OpenAI) + Gemini (Google) + Ollama (Local - Free) + + + + + 1 + 1 + + + + + True + False + start + API _Key File: + True + aiApiKeyEntry + + + 0 + 2 + + + + + True + False + 6 + + + True + True + True + Path to API key file + + + + True + True + 0 + + + + + Get _Claude API Key + True + True + True + True + Open browser to get Claude API key and save automatically + + + + False + False + 1 + + + + + 1 + 2 + + + + + Require confirmation before AI actions + True + True + False + True + True + True + + + + 0 + 3 + 2 + + + + + True + False + start + Ollama _Model: + True + aiOllamaModelEntry + + + 0 + 4 + + + + + True + True + True + llama3.2-vision + Model name for Ollama (e.g., llama3.2-vision) + + + + 1 + 4 + + + + + True + False + start + Ollama _Endpoint: + True + aiOllamaEndpointEntry + + + 0 + 5 + + + + + True + True + True + http://localhost:11434 + Ollama API endpoint URL (e.g., http://192.168.1.100:11434) + + + + 1 + 5 + + + + + True + False + start + Screenshot _Quality: + True + aiScreenshotQualityCombo + + + 0 + 6 + + + + + True + False + True + 1 + + Low + Medium + High + + + + + 1 + 6 + + + + + 8 + + + + + True + False + AI Assistant + + + 8 + False + + + + + True + True + 3 + 1 + + + + + + helpButton + applyButton + cancelButton + okButton + + + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/16x16/apps/cthulhu.png b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/16x16/apps/cthulhu.png new file mode 100644 index 0000000000000000000000000000000000000000..8bc4aba60abce5bad27bb7835e81253b1c8d486c GIT binary patch literal 685 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7BevLUI$@DCym(^3=9nHC7!;n?AO^PIi;lwVyaIwFfdtpx;TbdoSr+$(IdD} z=D2&-MiXE8+ z1p!}w|J||9duPls6W_A3GO33AquS!Wv7aJQJ`>tBGY2QA-r9lhBR&U(B+uPfl zd)Bh6lTW6cE1aW!;Gd!cgPd#NJ$0c@GtH&ybNzzXh8g-!F0txOlz8&F(!@8o>EMF> z0U9+7UF{6~0=+Iu(+@w~aN~}Sp^3?nZ{N&j`m`18?8&{IlbbuyYbgg?vsS_L7hG}) z4%bWPCrW&Id41;G*~yuioVT}0%F3!vKRxkW%8NH|R0KFG`s6PyUiHc&JA3tsw9PhE z63aJiY+U#HNRr{TYuA44_`~`3PGwcq?+HOn8T%P$&7OVRYpIYP*XQ+dn?F30t*-v9 zqo?=Cg75qLyQxpUt-W=1UR;X+LpuMbkK757VOL!rp1iEGEOXPYT}}!Tn|Kf3&=Bj^ zfA#g(80 pPuXQOpB5{esekq8KASzG%ZzigGTv=`z`(%3;OXk;vd$@?2>?JoI2Zr` literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/22x22/apps/cthulhu.png b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/22x22/apps/cthulhu.png new file mode 100644 index 0000000000000000000000000000000000000000..bb5dc5252b5d7d9ff5862d363abcdb59f3df7a63 GIT binary patch literal 1082 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rag4mJh`h9g^YtQi;>*pj^6T^Rm@;DWu&Co?cG za29w(7BevLUI$@DCym(^3=9nHC7!;n?AO^PIVH{5x4POeFfbqYba4!^IK6agU`}wT z#PRy&-?weoovod#zAai?m}N8Pwk5XZ+v#Ywgk9w;R11j#MA;G}zbYo2y%T4sKEb$)cb)-}h#JYX2j9 z!R-w9OG--iNN}*^WM5y$>cHV>HaoSbXwt1)QP#fb_xYxT33-c_?mqwA+RVl#$6H0{ z(XFl7OM)~*LRDv4&FJNKvo&!?X@KWpY$m%lSGHFaGWu!Da~)Y><~<%%G>9f%ou%yzRj{Vy;?Kt$3G&eOr3-VL?gm%}uU+ ztxhXeRmDfDO;(iPS@inX{b&)U?YDUk+_@tYw?3R{m)x}vZ{NOsd$hvl+@(uGb^ojQ zQfhY#O++dFNVShk9g zV`%8S?7YN`7Y3g{f9B!gdGN8qqWqoA#TV;MeqCQI&NauTvdg)hFKP4501?&)FWE&- zZ`zZ6cUS4M1cMVxy{B{hvpM|mq4J!cg-shb=I^ZfswLOo?mK(l((L1}=UCJ+P2WB5 z;>PzMe*di(tdqQnlHsoMy{`WcD9lRRuu%aUm^ zdgAi+TmIWD$jz;Nc(reOd?1gl{+YDTY_Zqp9=O}JTfn^R{k^@FhmZBXc~LdF=>W1 z6bMv^XE3Zu<^IEL!7RgGxAIfg{Gy#P7j3J*-4JzM7@{TE>Cz=EEPS%W>hGmje=n!} zQWW5L!Okb6VJXvBQ(XLc($%c9r#H=E*%zVvURbQ#Ra!CvB?VQ3e1_lNOPgg&ebxsLQ05(hfQ~&?~ literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/24x24/apps/cthulhu.png b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/24x24/apps/cthulhu.png new file mode 100644 index 0000000000000000000000000000000000000000..a015b1d00a95ea82d26b58dbdb0efd1cdfacb989 GIT binary patch literal 1095 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo*pj^6T^Rm@;DWu&Co?cG za29w(7BevLUI$@DCym(^3=9nHC7!;n?AO^PIoWwce=H7UU|_!D>EamTas2GGc%SG{ zndA1$zh8>x^2qGI;Ut)n$989eivVw@Vcx+bJw8G`{ExUf4>F{!*mL69?S_T=Qj6EK z+>MD4lRxq3(BVlZ#s0aTYX0-up)H8TYkS*;=)Cv2uf5F+`xf@O_9B;D1Fb!+Xz3Uzk5=7qC|p+sn*u@Sp3KzGK-kwM#c{NSMz)tGJ-Xe$H~H@KdKx zAJ)~??Rq&T&wi5FHvib>8gR*_`c%d;0s^O?|7?f4cnF zaNzt9nwt9b^VY3fS4KugGH@tzv>)c-<()WjqGMFlEQUN=9p{e?yQdvGbjUv{I(q7x zH#r-3>^O1jmej6w$r5aQ>VCug@wT-fxw{+kJoZ1fpxRV5V~`aX5n)~&7AU%OuaYM;Q}c=;tuLS?1o_S?FQS9hE8I=H&Jy54#Jee=$p zo^^GM%l+!l+_)jZ&CSiBI6h~6GT`TKrtf5iUb$679`{9G_@^kjEWw?9Iuip9T=yVb1{;nxgrYOZ;e|zBV{wXU3lD4f|_b%XKBeTrv zy14-_%wE4{eD*Bu@pQd!`TsYSyyh!l-NCtpIlUqGK|od2uijt3s*ayIYXMgSM>uWii)-5J3o*$(%ZH3Nh#s{0-m%clGCT;Vzd-vvP=<4=* zOe*24VBPTcx=VG~v{c_oOFC3M=QjMj@278>x#o^~+T@d4R9Y%tzrVEA!^-=n;wL`O zn-^!e1@$p3KDn3AWwKS-^nFL=IF9I9ZEXH8{Qu?k$K`>)$}^qSZr@~JU|{fc^>bP0 Hl+XkK|2hSa literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/256x256/apps/cthulhu.png b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/256x256/apps/cthulhu.png new file mode 100644 index 0000000000000000000000000000000000000000..c736f1158cc15de501a3b9c5333b0af0a34a6974 GIT binary patch literal 30247 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/32x32/apps/cthulhu.png b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/32x32/apps/cthulhu.png new file mode 100644 index 0000000000000000000000000000000000000000..0f0d058cab854137a8bced6a3613549b067e798c GIT binary patch literal 2265 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/symbolic/apps/cthulhu-symbolic.svg b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/symbolic/apps/cthulhu-symbolic.svg new file mode 100644 index 0000000..29ce2d8 --- /dev/null +++ b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/icons/hicolor/symbolic/apps/cthulhu-symbolic.svg @@ -0,0 +1,27 @@ + + + + + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + Gnome Symbolic Icon Theme + + + + + + + + + + diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ab/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ab/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..bcc35ef0cee86f451ebb563855760dcaa37732b6 GIT binary patch literal 27602 zcmca7#4?qEfq}uCk%2*mfq~%)Cj-M`Mh1o+VUQ>TgM<_V13v=;gQOG#gBSw?gQgS% zgE#{NgM$-wVBlk5VAvzYz@Wpxz;IfMfkBsnf#HV~1A`$01B040 z1A`67d}#&-L6CXU3=E1_l8c1_lKN1_pf@hnu$O5c%%xbv+nB%J<3)$_?g>{FG4#Fw=kL|ud&#GWiD zT@R(FKqF7bc#I0o)US8`#Yih z1yJ={q5QM*5c?jh?^=v;>BM9;;#Y)1_lWR28K2$Js(Q% zfYKKgAojn4>i@3*afhTL1A`I+1A~DgL_Sy%;{FUpNPIRZLi{xcN^ekv*mFdYfkBFa zf#EKc{{yOCPzfThs{}F6O^Ja)mVtpGS_xuar4q!vsZez*l_2TjkP;+b9w|Zm_a7=Q zsSF8cOJxQIQ&75AhWNKn8KQ0pl-{QdiSHZA5c{7iL*kb~1wsp{K+?O43IhWN0|SFL zRNO>`fkBUffx%4$5)P#*5O>c|VPIfoU|?9Q0!fdXRUq-c11f)71rkpWp!|<25Pz|$ zLi9_iLge+Kd_<@tCd(3IB3ch`ak#A^PV+`5RRs{yYE`zXnzR3d(0xgP0?# z2Jx?|8pJ$1HAub-g~}(YLEKZQ2Jv^B8YH~?q4Mk1Anw|)2FYI+)fgC5LFIuO0|PGu z0|SdXB;JJ7A@QiE4soxKI>fwabx1suy9(ch^F@#hLnh`%>N)g91;q?dD= z5PLsDX*MkgUm8jqXhGcXss$;p0<<9E8KDL7Z;2MfT^&$*niixSUjmiCrUh}|D=mos ze``U~BdazfJ#%S8%oT+4C82x;ZAkvq(1y6%SsN0rK~OqE8{)4xsQPrMc)m6y{gi4$ z>Y+xcd@I!aUZ{Cfv?1wbu{HyP3L^u<2B^BLIuP-@IuQM@bRh0~rvq{CHz@zF4#a*| zU5Gk9T}U_y=|cP`s|)e3k}kyEI#78dsJN{zBt5!A`KeGkA8KBuF2ufCU5Ni%bRp?% zvMwY%mqE?l4pqMw%0CFzcU%|Z?sHK3nl2nN-18PH{=*E? zUbHlav?t5VA?4p z20I1@hMzVJ3|0&b3>LPK@F})sV6bOkV3= zFfe?zV_@)MU|_JZXJF80U|{I9hp5|W4^j6PN-H}+)JHlnFnBO9Ff4F@q??xx3=EMB z3=HCq3=EbG3=D-(dbK0O{-=%%3@!`|46;s;cuR7E#N$>chhS=ZW3~9G) zaE6$7-x(5)k}i<=4t0T;JIw_mf6fKs9u8MXI0d>w+`qsTqV9?-L>-SCgm!a-sB3Uz zUbrQU?^u`VA$^gvCrHS zqCeXcqHnP$BpqDvg!rGy3zA;kp>(bnBp*%of~5OdUXbu!ap3F6aZv?}|QCDO(;;&X;h`YA=Lh{24 zUj_zE1_lN$KZrj}{2=CJ_(9UyR6j^OU-5&)1Cu`_9ozXcFlaF_Fr@iI)K7%c`}`sK z?zKN8o;3m>`6VX+qOUptBEC2Pl3$(&Fff=fFfjZNfRqm=fsk|%8VD(;S_2{RyC@JM z|2hzo4|swY7{VAB7=nTz?pzrJG5D|GQ@c0xA2@l&4h&_2B zkaDa$1XBJj4}pa5fe=VN^F9O;PG6zwte{~ts86#=n-HI#l50dco%B!qU4grv8^NJu@=90_s%^hij2?udk#|2Pt2KWh{NLo}!y zjDpBFMnU|wCJItt-Hd|NGtZ+S=6!~WvqwY3MWZ3=6r&;ONIx24Uu-laJ=aA;+|vhD zw*bmt7Y#A*Ks3bNSE3>H&_Ad;rWlC10x^*IlZ%1mZ|fKahUsh!45cv;_wy!0%-2nZ z)D!l}ko4e^45|OBlOgr$%w$Mq7+DeUjr52oWj81#K6FCG6ga|z>^BeC#Iy?IL}Un_-{E>{hCxr`r4cdvFBVW1A`g^1A|~1Bpxl&AoeCh z`8{cncE@%oeIgCgKDn6&G5g-u>5y=+PlvRtJkufW4orvC zpAk@X$>|VtilFlK>5%qNTRJ4)&rFBJ*U5B5%mPHyz?X$qa~lOfn$m z1Z6Hcaaq?}~Rf`p%0 z7DRtMlwY3(Ne3&kAnv=B1u2ieWZNd3mk$iTqC$iT1+)FxtJVED+uz_6HsfuW26622gP`3wvU zr$7u)xxmQ4u#SO&A((-I;Q<2!!)K_t2Gs041_p+IP%+Rr8HfpL&w$3nKcfHBCkzY>he7Qf1_p*RpnSjpDd*du`jM%LP>v=e1H)McNclUT zfq@~F0aB-cq(NhvAUcTw65pVaqN0*&J`GBB)W zU|{$I5@29p*vG)YAkPS?dqM3}(3qDpBcx9+$H>5N2;@fwNM2Tf>H$&585kH&FhJT~ zApT_#!2l_9K=oh|Xv~IzfuWlL(mn@CgZdF5dI4zM8suh128Ixj0H__wz`(%7$iT24 z%GYIt)IT6DXdHYm0|P?>0|Ubj1_p)?3=9lA85kJef+QIj7~X-#sTd&jzAPgHLp=in z10&Smpt0r2P<1d$4Jwz&z`$^ffq_ARk%8eVR1!4C2x^C~WME)Wf~t!G_172~7^Xwj z2r)wHeh_yJ0|Uba5QBk%AqPr>#@oL@+0Pjm7^Z;wGYkw2i=bkm3=9lxjF55?GL!@$50&j6_dBp4YOE;2AM zyaq`!FfepL=_=6t0H_TQ8s`Pg2|&d`)Fn{g2*iM5P+zHufq~%;0|P@AC_Wh(7}6OS z7)n8910w^&E(QjM7EpT0IcPqEfq`KQ1Ej46>c`#%#R~%iLn{LVLo=w|4ULQ03=9m9p?W_tFff=f zLh8?0P}$DFz;K;`fngE@1H&o?NPiWoltG&jQon%spz&T14eG~%Xl_OZhMAx;8pHw3 z)j;V+C=I3<85l$v85jx~7#M^>Wj_N0!vO{chOMA-4eGYvAcYFWr3I-)#mPmP1tkiq z#SE$%nRzLx6`Cmu`DqHO8YTH9i8-1n45}Uq8Tq9}#R`deDGI8-3b~nir6sAwaB&?Z zL5P}Qh2qrY{JfN62GtaWq{@<17+uU@ppaRTnp@0ZXux1^Z_nVElA@55pP!wZSd`7+ zm{X$QUc}&7P>_?EoLG{XpU2=>l$ey6tl(ahn3Aes$lzF7lAoJcl9{ZKmY-Z&tdN_Z zlB$qWT9lcWu8^Eqlv<*YmspmW4%LfCab99cW?3q+s*6jCN|Q@UixP9N>PXDVsZ=N~ zNh~T+C@x4%%m%q8QK29)JyoGRBQ;MUvqT}YSRpO5sJKKSJ|{mhB{hY?DK$MaFAt=IJpw6(wfo}r{<(4m!zg336}9$dO8zZ^r( zH7_wKCsiRWC$Ts~AwD;?xHvIAwV1&*51b;wp#)`@fD|&g=9Q!tfs;|Ux`9d zYFTD#IXGoNCVqfRY*?F0Sn}$rj;ll z3lwFhXP}Cd#V2sma+2N%<8hDswWEv%%4cWMFcBZW74R zC@NF)N{T9xwWj446djqliRmbw%}LBl z0T)R~PRdCvN>5eDPs&P7EOKZ)P!?d~pf5&_mT!ma0&cnhq-CknAW(EJ{o- zN-W4gR$G*ql9{iNgb~EWsUYPg`6!VG$rwmRmgbdZ7H5{ErYPiO=4B(Bi%YybzX%pO z1)$uNUs{ZrCJ-_>(gi{Rvcut`=;;GV0yT{wB+$|cLIN$Vz$K8=3tSK*&A??)(+#>X zmb3#`f}DQff@o<7NgN{`A>0V)(-e{fdb)y3ff5UH+JZ}9Nnda|^fU&S zKu%|HL9A&FE{i3-!R3(B9Hb)6Pg6iIoJulM6_SvvO^^Um?gMd?;MFCFmzJ3W%bFl= zDx}Z@G10U^>Sj=hs*stdkf?y{JFxP^;u3Iyi$^*K)S!T5X@&BP%;XG(Tu`GWF;5{e zFE76|FF7?gH4j!YfD8qfoG9f9NE99<7&0aK1)z2SND<6qr3HwR-=j1yJ+UY=F;Brl zAtk>=Avr&{pcGU9BP3wWD0C4c2G6|W)S?mwAJ;HfA5h`w1M)DaicU$*Ni6}@+dip@ zWuPh$)S`n|5PA$)g^N+db25udFa$tKKow_xngU9d=o_D3T*Bbz=ur0Yu4xq!n6dAc=qr z10+6jy@4#8nU{^ih1L>iVklgA-bNCIXKN%e%3KIsu{1T*mp~v7~kea6eN~WOpjY3LhVorWK1GI%>#SoNVuAr(>lwYoyq62Fr zs%k)5i<&8V5P76FELeT90#XAMBmz&DAWkMY^`@qP%4m?iNEsdMKZv0)RbU>@=5J7b zIl3IG)x`>khHr3US*k+3V=+T;a#3n(o- zXw6Sc(}S4?6UsvuDTcNS6^c?J-3fFBWvNBQnfZANs>ON?!KsNw$r%dqNr}nX<%vZp z#SFpF?twxHsJWL}Yz1}(SP-NM9<&g3Afckv;*xxD^F25tGp&RnII}9%NiD-O8TF_$%$;?d!_dZ+_OHvs^^3&6EQWdcF6~PXJsQ{(W;>?`X zykt;$nx6*hG^QqJFofh6DEOqNm4F%G`VZ3K1BvISDU@gCrR0}0gp?NLfvZMv^EyQ# z3DO-@$OqLkpe{xlL#Up&o`P#$dQN6Bq9ch#(1;;aFBqFj3_&A?(7eoKP-k1Um?0F@ zE3;By2!kfF{4|A4A>lS?woK(Q0= zn3Ka04;osiWQcc8%u7zqVTgCm$uCZ2h<5?kaSZX$?x%BpUI{dCVSR0wR53WkGQ@)l zHimeQ)SLo_c(2mj0)>)%hIpUEf|C3KhIpU+#1w{j-$YP1J~10Bh)0doc#v-t5{p2!97Cdll|o`pK}MpELXv_ND1yuKbrg~ntQ0_v=A6t_9fcGH zD}|KQoRUNxg;WJAh1BGXd>w@}1uKQL{ECvI{1P37bOkGg^!%JO9fb@9D}{{wlGGd> zg-iu2h0MH^%tRf9ECnlttkRs!)Dj(qYy~TY?97~e9fcePD}|iQ+(aFPTm>tI+|2A$ z9fdpvD}}uLveew9)FK^)d<83o{Nm)qA{~VS1uKPu#DYW}g+c`@g~HO*q|{^`g(3wj zg`)i2)O;O^^dqC_2q5(O)TlEl39d>w^S1uF$;)uE$MreLK|mYH0VU!Sm*%GBq*gE_Du4viixSH~G-yF76R42}?dKv1<&}UMimAB;C6x@Rc_|F3 zpkWRM$e0B~T4HfYYLOm8dQoa3sCAc-SgZguJrh*oGh}3@XMj{>vEly1a8&nLc!=OS?mlo%zfkU;p1e9u!>KRZv z$xdZJ9w{|I;TfXvj8J&SC_EDso+%2?425To!m~i(S)%X~QFy6^rHMJkC_W-ka-b=uBAVWz}YARx&r7X3mBr`cN zhXKX_XDm1e8bhGWR-TbrlBxj7i9x9a`9&qVzQyU8DY{Oj>BYJs`Bn-UB_##LR{Hws znI$=iNqXsd`MIfj`9^}TQBxpY`Q%2!VZNC8!qg)u=m223tKPj zy4VP679w)jg$CHeJ|-#xnppZ0m*H7q(v5b7AX+y%(D<&AvSI!UotZ z!i5PJHea53u^SYdm$rf;cf-Xt5aVLQg$=N2g$oldEx*`tvFBnp!-WYTi3=M+zE-%f z;nKyZUCi4g$p|_Y`C=l z!iEdGF1B9SH-xR5E&xH*N@t~NvvJ{jsAu$7r|6P}7f|DO8 zz%J|sg(N7DFYLYmu?{2FKso!u2AC-z6G5izhQ`rE^P*pNU|69fQ;8; zxG?d;)(g8Y_FUKuvQ**1<_r5S>;`!flwv_b@I--}gcJ-xvA6@2{w{2WBucDigPa5k zvx_|p@fT)XY`CxsW}&Qdb3tz00EtOZl)V*Wj9C!-YMdaOwbs2DrT1pm1UPg*~7o28sw!mA3a{(}fKnXD`3l0jf+v z4nX6Ai~!XwU}He?5C<|`AdtvF=@N@R1%?aLFKoTA8B`f6T-b530hCNYbsEDZa3Kt- zyTCDYVIw3(fzlSl6+Iw#@3^qxVk5{Q;D7_=a!@+EumKcWh@3{8-pkuTC${qV+ZUBqU^fZ2x_2Q*aWJ*aD@=6 zS3wRzu}b&CMsPaWaA`gc6F}jCoYg_`3ChPHqfiaMu;Ic!ka6I~UlR`FFv9-Q+Kb&+ zmO@n{XUOdr+aP6Z>qU&DiNzF1{SQghpc(|(Sdd$hQ#Kau7rQSl2RWkU!oG_QpfVQ3 zA;xBKH9=%FgVlnDyFlp=(gFenC(h)J9=@>R98^Pqs|wxCWQ0s~aH zke~}x;G;A*Fg%3CKRYgL2k8UliwhgTzPhj-qz_a%fD$E<-h>$gj#pS!Nsd7qE^Gr; zyx6Usabd%y2a?Ie6#3ZQL`<=d zT_@q9AG#u$GG0-35v+l$;N$7A`HvQ8HpT1DrxZ&2dn61w|-m z`~qCAlVA*}AqZ+x6H^&rcLunS$LjS7P$`s7C8Rn4`5(Ph!EQWwu%iJq!~ku#VrT`m z9>IP|q%>_JHwq<9xiC&A_tRwqE~1yDjlsTn}Q4{9BP zYj6@m0)N$j)d`@{JMhpG-l7Rhp+`&=f!#(>W+GHgVABa|tHX-Xsss18J{EpV2u z7+z2SjiW*89z2x>3HcjTlM`+=WA-aRnG-t31nIkDNr(7{ov>KI?x05b1l17dIuWH+e&03MP9*-efn zVuzVf&1Q%PjZc9FBtcQ5%^AtU^_+3mK~e)pPhQSqvJ30JXe9<nrGiZPm$#_sQLg}L+DaM+1&|7S% z-EmCadZ2aTgN9^58bRe8mX0{g6l9-X zSPXS6a^NXk>;MfmLi_c&+g1<*!6VdG&%ro z20}Vy7j|6Q4=L~=J$O(_r2v}E165=f=Ys~W!Q-ExfrX1rAX!L~=mt3#BnXQFE08$y zEFXO7DX2vSZkxmA=#UqoqE5Pj+My_BfF|4^&V#f*AoF7vc0-2zLCyh{l%P54&7cbP z!hUpDfcj;~^%sg^pfCd`B=FoOc*YMTgdB{ZaU`S(B1oGJ6pnZe(gSz-;LZfk(jxf_ z5{D4KAZjYmTzxS(;y{xipcq5*43aj`;sMb752QVzimDAXRt}m9yHtDr~n%K2PHC4f&jPRzl14yAy) z1e!Gg&$J^lBbox_XoBQc6a}Ed8H5&~Vc3f|=q^kEEeZoI4FiqDfC3Fv4S~Aj z&=L~VpaJE2cxehw*%vlm*anrk*b3^k!g4RhI)F*wr5C$FO;AwWVsSk_6$+qmxU?2j z3_uEMQ0b@#%9zkO50KqpSA+L^sHTA20bbh!Q4T7zz{~SNT+k#is9yn650(IjG4gU2 zl(q$^6A5aDfs}*FOi)n;%HELSD%?sH^cdnVOhDuWhIqu929OMTfP=)YKt@hLnIj&& z25=Y1R*(#|z5&UgC2H8Jta#8+2S_<6Y~hI+q!*MGE{$M z0*Qix2b9#o%PHc)@_Rug^~I(O8!t9r*aZ>+)p_7RflgU~#J~-s&7dp+Y5;>=1&S=t za?FjOl(hX~GsrOv@u1BI7bYNi5FBjq0w?~$1l$=s9?NP-$htbzXadDE$WpjJz?&FA zY4TzZXk-hrli|Wfkc&X;5FpzbF1CZx3n*Jdb~J$3o$dxLMg7<_Uf2iOApvSTf!k2vvav+LN&&PU z2wdRpgKU<7lqMkmLrQSSu89kq5Up0o-U*Nh*eyGBz}qLl@{N!U6c_t1>;?G}vW4Qp zc5nzZgBGnSSb<^=yeRs@UIiV63mZWqpn2(i7n^ky6fSI1umZ)|#b!|XprZf+7d9(c zfzu;sNO1#9>|&1UVqNT3Pyj6zvjPzpHeA>OS~I3_VT%=r1xnE%yDn_GJktt9fEp{HHvPpO1&~9x zT3y%*YHfop1qo~enY#^?=)gRX`?i6KrVATEYXLw;DS+BuR$vm;CA+W%$w*LGY_|d% zxCi8n%L}c*V?SF!Eg4uj4zgH5;qt=EGeN-!qAzws4BlaNVFzf)^nuZ%WdGK4US};D@(1wgEFAyyb3xB7aOcV z^&_ZiP*Bjh*k}csRJ*X_!WNKRlNC6R?77$tY88S-KoJ0{`oPf$THp`z>{_c!Ye8ib zsOJjtnu5ZmwIHRSIbTp5f?T6;vDped0(h|j6jBfuUu*&8#1>E^8$1uR0p!<g@+3HED1d5ME6~gb$Xk$9aIxJAu7+sCoh=KyYM$G=tKuf)$8_m7N#%Dkxm+wgPnpL3tV!87r+oi&w#M3>qT;bLU0591Dadi|FKp_elm;|rx z?YXcO)O=C^xfCRDVFRc+3m%#SWkA@PR8a8%>SKY|WP--DTS0A0WRVM787{22*aNDB zLGcXA6yTHw+AjghV)#r0mBFA00T+x=_dwTwGJv-ifR>kok`ioHC}@y&4>%MzfTmuM z+_4uFm>_dNi(@x{2I;^lXDv8IZU!|NH$WD_W9(-GweT;`1SJsA^1;h9!Kn!}*avbM zsPx|fZW)25CqT>ZLFomQ1}}CaZGXcuTn0NW3Vu`+C^^F?R2VRIq%eRA08p|8r3CPl zEvR+|sRZ}6^kCcNK(TmvCMdu!Z3l%gX#NB|<_20X3@(2`OEE$5zx@KJq0@R{AIR>t zpq@RbZHh6p44Puz3ko;T&X292%H+Z>>_&ic5GX9c10kT?1{zhs+=d5U4GC(EHG;}P z22f`ml(!+A9hc^Vvj}LdJ}3pFc?9HC@F*w)s7(o}<@6Ykx9eTlfI1kCv~>^EUPes1 zfMOP0--3FIpwbas#Xy>9h_*AxLQvSiCYv@O+7cisc$9%SaCP9UfVQXthmoKN1hslV zV-~wXUBL~w6@tP7c_b6JQczTZHsLgYQp3d_kR>Sd3m^el2kBx1Xubjz`g$N?&}@QxwSJSIp2&H<%*&{z$8F)agpZz8A@1?^XWM!+!lDT1oh3)?})fm%r$F1CT1 z@Y_Mj8WI(tkOK`AZn?1I!amrBMNoeO)WU%%0hJ>lWys?;h^v>h4C+ zevQjBL1i`r(gsIR-32a4+rah8F7Q|fc-j{nIEe5ArPGVum$t*g5XCB34+g9oH1P*2 zOD=4HG}1r?D1nV+1_b0mEh_)q^5>(j{FzI6Jm8GEUi`OI*0*06pkT)YB zZ%#nof`Ggw0eONR1XT{8#^8m0prV4HY2XoW@cJ9j_#bpS1#bv~TR?k3qmKj(&m$mz zVLzy@Bf=nXABkikmuTm#-M7^vkDC{yo16sioM zF2{v^;4a)=P{FnZ)Kj~#^};4ljRdOBKz$8RW`I^IRgX3gc1e@aRvs4 z6D14`LJSNH4@w~Re}?jzN*Ne57#J8tOCj#CD`j9%U|?WKE``|BQp&)<&cMJhwG`ss zxlsPLQU(St1_p+Gr3?(53=9k>OBooL85kHYL*=iRLc;GpRQwH8{6i@N0~-Sa!w)F` ze<=e42Ll5Gdl>_RIs*fPKpDhdi!w;KdqU~(GKjxYq3Rl-;w#D+7_=A|7`Bx$Fi0~n zFgz@SnE$tofq|8Qfq|tQLUWZfFo=T8FK1v-V_;xVD`#M60;Pj;1_pTs28Ije3=9?w z3=AL285p=37#K7wAmL;RrCll@@ey3Xz+lM0z|c^^z+l6`z_6);fkBXgf#H1x#C*m| z1_o0G1_tp;h&jHM5c$YTNH}I!Li|?@6>q78g#WZkh`aYg^&P8(#QUX6NccX7s{dFC zv4^<|LQ7ULFnBO9Fz8n?FeoxGFjPS4Syc=SN(>APd#WJ%?^i+G|FR0=4zX%TxXD#R z;@z_v;@`Y#h`!ot1_n6>28IRI5clt|hQ!CkY6b>j1_p-v)sXb?xtf7NmVtqRrv{SV zv}z#XlT-sqM^kDb?%Z0#z`(-5z;L<-l8-LbKo|CnZbax%fzg-JS2QO4mip;$MY2h`TlFAmM6L2T2!! zbrAL8bR#)I;*)%zB7Bw$($z z>0&)3p5E6pFi0{mFbFn4%+qdw@V%h?lm>{p<_3uVr45j9IRF)Z(!juA#lXP8*2uu1 z$H2hg*vP=3%fP@;(8$1G!oa{VuMuMZLq`m)%Ve|6gumV9;b>VEEhwiFes%NVpm|L-;Pu z5cN^bknkvKhQ!N+W{CfmG&3+*g37CANcv)Gfy9?|3nY9DS|INAYGGhdWnf^)Z-Jz< zsVxxyY=eqlg{u4A0tr8bR!DxdZiV>Ay%m!FLRum2N^WIfFl1z4sBDF#x7BTsa6H!r ziBINsh&y%KA$*5+NP5nM(s}I=bBo&{?rms??#od6c?ZOO zzdIn|E6@qyYj#57#STh`LFqgw-PQ>)XI>{n-=S7Gj~DiCGjpuxa)O6 z>K#ug9n%G|Cm+gh?}EhZEU5SvsJ=5${_`$~z5lx)=~=iNVy;0q#9Z%gh4&5{$9_mY4~Ei-{Sfu}Q2CC2NVz+!9}>Px`XT9T zM?WMTAAs`D_CwO+)qY4izSj@&-^+eT_^?iZq+5jvko2cM0g}(mCqT?`o&eDwFac8k zL{5N|4{Z}5>1M+ONVpxF07-{WCP3oh=LCqqg(pJPnN5V4?=ul%Ud%*@KU1ONg ze-b3V8Ye;Oj~SC7?wU6VQZB5U1aZgpNs##dH3{M$p~(>SI+G#sYcv@W?m?3w{!4?( z*Gz`QW7A|vexE-XV*k3y5PNn*`KKpC%BLHXA?bm43M3u7O@V}O&J;*HXWA4oUc$m+jK~HNKc2z>raQ+ z;{xS}PKTtEtm%+==$H<%ch+=Be5{%d39o}tb1p#nPo_h{_cK(Sa|T4c>t52=9|uh*y}nI z5}z?MA>o<{eTv3=9sS{@+4Kd#++3#Qx0-A>ndt zAtb%LT?lcq)?$czcP)na|14Dg{$faYGc1AV z7hM98*Ixn&e@7@kXbB`Ar7VG@zk(%@@@UQyNI89G3B;c3OCaI;9ZHKXg`@-HrI38= zxs-vy2-Hts3JH%1OCkQ+u@sWt4=#no*C!~gunZDDe#;=?T(S((ADX=kQcfRR2GM_J z8N}UJq2kY%LBi?nGDtlBg^G(VhxkK!IYeB2IV64BFNf44DNyU*XYknmGk0WrsJ1w?)13P`<{vI5d>&RYSochU+524e;WhE*#d z;c*WtF1Qj>FKDiWt!4pIg^J!sYTBNP7RZ29nOD*Fw^%-dc!xQEMUo%2*4@Pfcqf z@iBWX149V|1H=Bc5cis_gQU0Mb&&F}avcMBoM_HE1_l=f28Ofi7#Kns7#M`sL(N+c z=}$MUXJGJVU|`s_o`Jz0)Zg0x2?w_g5PQ-#K-|~00a9+S-oU`%%D}+zXagkuYHWmr zr{PA3dmT1H!x_pi-Uunz8#hAYr4!1Zwh^L#-bP6LEr-&3p!7v3{cIz|{@+l2GMgab zs5_MECP+2ZGyzN+-8VBy*ER`IdwB6TzWP$F!+MTzcxeC&)>}u zcZh6(m?ygh!dKq{iC2Ryko;n{1(Ke;p!}FEka#YD@*B56{67^+FWv%49~-wo()*4r z5O<%0s=o=<|8@%`eEvc0W!uWYkjucpz`vD&VK)NcCsh64ZIJL`+YT{TVmrjW>QGv5J0$*1w?o3iX*5QEadx~~K+*h#^ z;;&XHe=<~l0aX98ose|8dM6|u-Pj3b8{EOT~BsF^5<8m zIb6FT_N(rOxJPq0#C{W~xZQ4uc}`Hi*KUYA{h;bXcSG!t-wjCzsk$C@AemIoQg^D*r)y>!gF=yo- zNd7*u2NKRV_CU;i4ORaeN(=0TgsbXai23$=A?Alb>8!nweA%!U(yp7a7viohQ2O*< zh&_*>{BKb6c=tivp$?^;_Cf54-3QTMz7Jww-#$nv*Ej^pXI6(G?g>8xac3Ts zZa)Mue*sk8oVTgOZpmf4vNO+VThPc1$FvMMppyHbjL)>)? zs{Z<6h`ZiG`TwDO(IXK5svm)v?+E3GAAy8N;Sq@Yd!X`*k3j6%38ha$>6=h>FONX% zVK@pYr-hC}%vFTa=0_p!^*stvmwFUpe)&;II_f(L@z-Lg{B|gP5-NThYR-Eo&3X*t z9_eEcbG45_>~lT_u|EHy($SSN%}=X~!Yu-R$F#a&10T zemPX%y5kUk?0~8}ejHLRo`&+T9f#B_w~j;FMT{pP{ZO?N5OMz#5c|qbK+(Qp!PLD`7@#V=R)-_hMKzys%{fh-RYB%cFFmZko0mJ>aGt^`L8D-;rA0N&UFgn zUj9=M_luu`#Fq?|uYL;Re;uegt5cBpaDwvvPeJ?{ehLx}2~d40ry%Jd6DnQ-)mL*0 z63?BdAno%FQ2p0VLBjR^DM&tkb_$Z78Bas(mpBcvSM4+;zZjo}?eQQrc{JrZm#9gOPL)?1{%D;CS;{Ug&A^!Pv8WIk_p)}hWi2Z_4TJ8*_ z9MV1mafj;}Nd5{x1JRcVrE{S2CxS zXCdL_aTd~_%sUHFH{&cs|ADg*e;z#x$w+?F0)^m{d;z6kV zk#msnJarC|{;osm`{y9>^Bn5lZ%}nS=OOVbc^(pvy5}L`Xm=jse)sbbbNtRj%ngI` zlcDOeq5KjkzveuozH2=X@%N(h5ce%R4~f^6=OO+)3{`&)YR`43Irq*(;``ZoNI&Ys zc}TxZ_yVL{Gr0f}kGueJSIq@T__bVsxWDrPq`f=q0%RQI_yx$k;wPxM;zfx0eitG7 zBQ8S1JK-Y4y=fOA=4D-k8()tgHZmJOAz-wxCC+E*GrIa;JXYlPxvy#J$jcR;-;4& z?y|ZJ2}g&^5chdN=^&`O7$}{18B$-SU52>71u8xPs(&g}-(09Y%P&LXeI3;P^HBY- zE<@T&99JOzQ@H{uC(NO==M_jgh`s`GU(OYXdyB3>#v977K-@e13d9}rq3Tv&f#lJK>T~=3Z%Ted<7D}ub?#3RR~||D#RS4s}Otau0r%VUxm2C3(Aka3h__URY*Iu z`6?uzEWHW|mqSqc!BvPm|3THsU4!r)u0ixCK>3Z=Am%KD(uc1>%y|msGhc`BRj)(Z zlg`&6`61~#B>Z}>L+oD(kaUm;<<~&@Gj2fCZ@vL> z-({%$7pSp)G~*qJdVVM^3#GN8v?Y{wzXM6< zp?4tZFyjs+z1KtKC*Fa$Z~h%fdfadaQjVRt11T@hK=pmR14*A8cOmk;cOm&h@GeAL z{4OMXWbQ)zrEwSHKJ&W}|GM6V*b@q+)9ymtRel!|A6<7L@w?iY1dl2(upmaV|zUdys+(}UWl6w$$ZGnm(y$313uHS=% z#|NnS9QPsdCw?Ddz7CXcbsyq>|N9VkXWoanuk}8}+^P2=?pOvD-+3Pr4=3+K-0=Wv z-Y2Me3=bgoh(3U%3#|u`deh+nBz%1zK>QsE70-A8v9I(2#J<)C5cf=b0CDFAsQf;t z{5dFn{{h7Q4-X*zWqJs4zciFKhtk0hA@=1zgt({fA;jD%4*NFKN-qj@Cai6 zdMJN4ls@$c;-8z3AohNG1PM>h#}HcXF~lC@#}M;eA4A*|^cbQq;W5PC%Eyp+oA?;w zo+VK6t&bu8I1ANx7pm?xl>YY^5>A3oAmzCF6G%SMdjhe?1j=`U(jHGB`N$l&=A$O`k&I!3oOudkXPS^ixPU#Xp7EpAR*! z94g=Nl!4(cBLhRrQ;2_)ohBzUPqen)MtqFR;VHD!+u3^Y$+x=_(3JXTF5!t9S`1=lfqWFw`(GFl>GaiC=?PkojH5R}gi@ zuOQ`L*DFZ`VB;1%Ns~|%zp!kht*L2jyI5SKJo?=o+Pk9S5r{papJvF_B)UQ+CLgrhxzlDU; z_qPn-^>!TZAngI?caU_R_YRUiN}+W1J4ij<_zvRFMei6GrZF%uoQLw$-b2=FOnwjX z-v3?w#}z5^gg-Ld;tO)qfJI{^mzWJiLa|Y@Zkyq8Jz$ z6hA@cziK`~=2KUEf~*s`_6g!XfzJ?ewa<|F4EYS{KgNEB%uh}F3`s{PKSTPDkDxTq z7l{AOzChgV{RNWlV!lA)qvQ)DJg0wwgv*gHkofuY1>!H8uMqbpeTCG^wO=9THGPG| z|Mahra9H&f65o5iLe}q|`U*)8?B5{%GXDk{4@mw7iRZ3wkoej94U+B-eS@U$W8Wa@ z{q8qN{r&wL#9Z<35O=74hlH!ccStXuA3Vapxi^eGaPb*AIw(sh<$q;wQx1u%D22Z0%1-{+k1pKl&5W4t@+( z$NCGRPv;lJKCfSpd|vtslE3Hvg2dm`Uy$&U`3+f@;qx0(u5|r|#P>QVz5O>NJP!PZ z`1{;%h`Yc1hPX@N55zq8KM-|we<10x2g+aY2a=xG{egu0zCVz3bLbDmowxr$`lmnt zK*~RjzmRxw`3sSc{tNMU*_k%oG3q3rT0@{~+f3|AVN@_y=)! z(?3YKt@sCtuZ#a6>G1hKNH~f7huClbA7W4Re~7zl|3lJE?|(>onDrmxo~{2G7>XDf z7_R(>l(X)Pj0}DZ3=BDpjNo(k#dGJ@A-i7+vO*WbG^F@o2#`!F$r_Xh+q zF*1PGyC*~W^-PT5{R$JH;&Yi8!TTF_GBJYp16+gBADI}z>-Kq=8NuuB#hDqw>-`m= zd`D(R@ID1EC>;ran~%U_*NE1@Ot(0Q29?RkZ|B*Wd!dFFlB}4i)Dq_QwilyVuiSW z9aQ{0E5x1`tc>7&6-;ap_3CU8^BveA?n;L88=(BfP<02`7{Tj`Z?Z9h*VF%JgP5nt z4)KRIJA@z14slN|JH#KI>=1jFutW6ig^J&2hnV+^9pWDa4v2bp4v6|BD8HJ65xfs! z8dQ862gIK99E{-g@Gm(S!TVBpIU(k&a6;^NgYuK0{1#4#xeGWU{@=+737>nM5cB?X zGJ@CZOL9Tr4M|r&p)@BC#2=D8jNp9;Mm&)8AIJky z7tX^7-glAC!wBBjQpp2xM-LAp18D!nEFMPiy7&t`knsA?!wBBzqR0zzzZaCw;)RHJ z@j}9BGcUy6E4+~W@s<}7j^B78=1cQ2g7@WU@-J6gA?7FZL&CL?A7XwdKg7Ic{1E?cf~r5l&&U8;Xa5OG z%LqW?*G&N8o&*6%x=Ry)q?;ZANW3qG${!Sf#SA?LeleXK}h&92|>)$hSFg|jNo-hjZpqpA&9;QLX6<`{ldbG;Qcec!VrF! zFeIFg2s48B2b~v&*ndqJl5gJ%L;NQo0!a^AP})-j5?>i2koam8fvD>efuye`B8=dD zKRZMq;d%~AKNEq(_dlq9c~OWx7En4`6k>lJl%6UIv3HFq#Jtl`bq_@u!TYmV#31sL zVi5OOh(W?T5X#RNgQ)8egQUl~Q1$zv^gXD$zhV$~iHSqv-&`CL{~_X#{FDHt^PzMd zl^cn4nz6(B_QSV4+%&*P>_VgvnQ0Uk%ZJ^>m?!S@xCNP9jg?izSEOp1h4N* zfb!=_LE`^{6vY46r6Bq0ixkAYjM9*Nz%LDnXGLj9I9p3Y)JIA~;<-#3lCS!tA@=Wq z(r=_8`Bz2;>P{Jme`;hH8NwMD7-q;o%DE3RkaB`s7Lq=-Wg-4dm1P94Gwqdy#P@Sq zNP1wCgM^!m93;F{|**^F|&Lu96B6cRDFR{FS8u(buK`35T-^ zjNtuZe-$9^a8rcj+c-r?`s!4Km_I`iV%}OsNWE|ks_vH}Bpy|jAo1X>1Sw}@l_2Ft zj}pY+bD{E^l_2goss!=>L#Vp9N|5ySPYII#_>>{`DJnz4)k_&tzGW&y+&x(t5+8?^ zA@TfJ8IpcLi;qD2`HWN`?u=A{xT97DVtyZ#KTidcuGXtS?AZpT@2f!KjYAb;o`5PN zczwK+DkNO;R3YhWrYa=7wyQFN*Xy2Fg`^7sHAs2ur3MM-05wMNdbjCnj0{c;3=B8b z7{UEF8FdIhR~=%{26c$ON9vGpd7%zT&tKFb?%~sbxL-^I5}#@s5OF^ZNPY;@fRrQ2 z8j$j$RRiMxWg3uteoBK8++V#1)z^Xe&jHF0(Sd|pst&~5dMJOY4kR6~ z*MXRKLw)_;;y3ME`z$Muuz#28I{<5d9$r5O{^ zU-UDC*t^FNQV%~dWMl{f_3w=s89YJzNR1%oA2NcZqt`}|_)s%u1g~3nHHMViEyj>~ z`;aljzh{jh?t5YkG5?=2#Qka}kn-Ey1QLI)P=2HdB;37E-o1yeY6G*;% zZvwGT+7v>onL^4@LsLfZ{%I>yMusB{3=F-djNtXML1vJ0W0D!f-J8rH{`qLe$dJIm zz@TFe$v?g35cjP!hlKMUb4Yo7#T=3@@0mmV{|Ks%(E^g6_$?suFKq#Fhq494933ca z1r_(OfW%Lr1tdL}SU}Qcn+3%Fg%*%_KV$(3$Lki14CxFE4DT!$84iNhHCjT-F9|CM zEpG)0XEiH`y$)88bm|G^`&&WWA7KS?UlNqgvVyp~$O>YAofRZq&xD%03`(zss@noJ z=KxgyDJzJ3FIhq2?K4!K*&1RWuQkLU;?|IO*0F}z=K!UBtRe1+u!fkEU=4}KMr%kq z>9K~mYpyjU9Ctv~AG2m;Fk@t3I0xmk+Ct=cZ5hGqKBa9T=E~VZ+@WR*@s|OVZwpoL zZVPdDs4XPFrb6Yjp!^bBNPSuf6<-E5e}gR~9c;FRg#UJ^`hB(#{~d;kpSOkh=Ni=h zhfsUpLFqqGbGhsw?iI0v)CV$lknr-egXDuGJ4m_NU>=f(ggwOFdiD@=tn4A-W@itv$HN|?KhPfH-*BjW zoIRvG%dm%pd$m2p-E~lXlc46!hU%LSo@n;-VUxow3{yYar zJy7ic@qd>C#NNqJ`591imO4QEzY!{a1WI3o()S!7>FYIA-ESzL&k-Un=Lm6+o+HFQ zD@RDW_jH8hnE;{L@@_3NPK?1!p5?Fez#Z7Ba8RQ{hMB>uRZApRC~ zf`pT_6GU9o3F00DCrCKjKxro@hCp)0(4?xvjbcTe_9jN`Up!R-;n$P9}u}{(k zqE62R;tm@Zh`aot{CF3L`wLwl_SLyS+}{orpXLH_?_w87xNmcT_;U|b{Ryb~7oq(7 zE|7fx0&35H7fAXSaD~)YDz1?DvVqb*t`Ku$Tp{6*AS8Fe?ErV^9HK^JCtU1gSbQ34dPA-H;6qN zZV>ZK+#u%Lxk23R;|58eL2eLpBi$hGO@hj2LFEge=9ELtX@;8L>jtT>=ej}sy$5Rl zaW_bKoq?)<0yXcQ8^r%#+#vDE=ni$SJH#Cl?vV5&?+$UFvOC0Gn(h#H8M#CJWd&95 zH+chZm9eTsQ4KVNcy_u0qGY!gNk!| zLhKdvgqSDc330ECCq%uHC&WH8Pl!7mpz=PR5O)T7LhO%%>W_!g$xu2SsxKR=uiO*j zpIT2ycy~k1pW+FLr+H9)8$2QY*y0JPFAqZX--60NfXY9CihqQf^Bw9RMlVQsb9h1A zC+r0=U&0IGZY?i}JB*-w2QP>}J-i^{5Cqj1<^{1o8Y*7m1xXhbUJ&Ba=L6|SZ}Wll!~Xg}@`;`=L|w8k#NX3= zA?}*%3-RAdUr0Y@qc6nY?|dQd{{&U{*B27roPH2-At){D2T`x#2MHe?KZyB8P81ckI^GrlG4FH$ z#QhfoApOzXP<29qjNo&Z+yWuvjrD;Lbz7nI{y>O7PXn9#5(shs4JiLfAf(^$ zA`oI9a}Y!yXAp!h5CjP)F(_Xy2vVM^K*g<~;!Z&j`#qrggP`J(L6CG450%e?ikCpu zRYBz&gCOzH69jSJtRP7EFAIX?-_1dg`sWaoe+#PaWe}wO@D-|_Ef^Ah!od*z8o?0v znnG#sV2FPbgCYIf%wULpoxzZJn;H!9_be!XK`_K!OQGg%4u*u!0jN30gCXNH=Yt{P z_!+8?F9ec4ghL?ikO_h4(+q+1#|=Ut=^!QqGVah90vR{k69RGX^AL!8{z7S{P)PZ~ z9tv@vTqs0dB@~kGHA5lc>>moTCn^-`&rnEzF*6k6o-U~TrQ{4k^#4K=m(y znzt1yz8lIv4K?o~lz$@}5+C=%A^v{^75@e`=MR+68v${*FqD>r((+JR6-sMEX+tP& z4yA3Ov~vU`emx@~@e%>$7e+wRdqV^yp86sn@vs6)Z-vSqih%g{0#y7qlzsuFzd~uI zNQi!ZC@lk}H6tPMU=|6&AnN&|Ao*Q33gS;qC~Y1EiBH!kh`aot>f@sz;gAPa*8x>G zEeaA3^P?c{S_&0k4;9}5rT0Za($x{D{28eFt5Fbl-iNAt29GS;P`)mdHjRPA zzb#a~M+_wXV`3ovl8P8e`7<4=e|-!jJhsI^{Btx0;-2#{knp(#rEfsh--D`u8Uyjy zml#OAGsQyO%N+~J?*g$9_bJCh+^rQ0akm{*+zm?m#zO23iG{d3E*4^cW-P@194K8B z3yF^ksCj*{5O*(v(i@@lfmn!p&O^<;5etd;M^O1sP~f$IAKRreq2e&%?HJGtW_{*jD_gr{OW#9i9)5Pz9NX`6V6 zdmQ5-;pY_(@lPa_9}6`vCm!OiDyVo5RNd@&NIcAkif@gFgv$}A{MC3y21W+RSp}f; zApAjxbArzQWMN=f3_53miGg7f69YpB0|SF66X;-428Jv~28OR7O$-bSccEes83qPU zW(I~`j0_A7ObiTnK<7=eGBE6dswrV)U~qx5y;&hTKxYC7gVwpSFfeekFfi1zFff!r z-LRRFfkB6rfx&{2fx#1M-ved_hJ#Qud_d=kGBPksVPaso#K6EH#>~J_$;`m8f{B4) zJ~IQu5@rU5WsD3A>5L2v_n~^`GcqvfGBYsTXJ%lCWno~r&%(g)lm)b|ih-dGY6r+= zyete1Uzr#fBtVBzf&>^C7_KujFbG5WHjE4mRZ#USp|m_R1H&aI28MOa3=B%lkaf8r ztxur-nZd}wPzX8;6v{us2wkJd%)sCcb>9i797ta$0|UbyMg|5CRt5%UMh1pbsN8Rm zBoY>2W?&FtVPLq!%)n3pRa4Buz;K#{fuRs;t_%|c!v#hL20a!A@H(<5Ah$r(f{ZF- zW?(3Tss-^+Lghl37#Omc85l&F7#R4Ve&5N+!0-dg)?;K~=w)DF;DqW`XJugEW`vwY zvWAg?VKvm8XABGsw^$e$92prH{xdT$6hp%dbOtWSK6hw(;9z24sA6GYSjo)5pbu4( z2~q%>tAW~S&%(g)j0tiMVT`$6?__3R z*vtS~!+L{>f#Dt#1H(fW28O9D3=Dx#_g!OPV5nhYUCw7#Pw(=NUugUxM7g%)qc78jeXU3=FC!( zplWWjFfar$GcZU&!zh)RfuWz7fgy{DfkB*^f#De=14B2|tsw1gj0_A>ERZvTvp@o% zvyNF97}}W_7>c28=w)VL$YEk&h+|}62xeknP-10Zc*(@T@E(*#m>C#0GBGeHurh$> znfF2C!H1E7ft{Iw;RfgoZAJ!$U(5^)R;&yRI#Bs~CI*H@P&b3DeZ|7SAkD(S(8SEZ z@CWL?8&G*s76yhFptJ*Z&sI=*3o7rK85n*+)qu>1fyzfSFfhn7GBA`gFfhn4GBC_% zVPN>i!oVN~wRt|GXp~qBLhPq3j@O*1_p)@Mg|5B76yj3%nS_Im>3vrq3)W< z%)ns4!ocvGnSmjmiGkq<0|P?>BLl-*W(EdRs2k=pF)%nYF)%Cu)yE7B46{LD$P76z zy&GgPD1Mk37}%idFEcZM=enU%3^N%ZXPBLVx(y_r#LU33oRNV+l$n7c5G26Bz;Kj_ zfngpa1A`_L1H&v(ozBd_z`@MGU=DSwGBX2%IwJ$a3sAWRHS0PP1H*PE28L8d1_l-; z1_m*xT9A>TbFCXe$OqM1j0_CBU=pBu6>85xMh1p4ik%@s}BFF$F zypV~3VFwEX!vZD-hA&V%ni&`vxS`?3#md0&go%OSDX4AE%)qb)Y97dl7f^OMBLl-c zCI*HACI*J{pmX~f7#Qjq7#ONRilDfSnSsHCnSo&j)Q)}@28I}B28Nf+3=Aik7#J>t z>Op46{sgENFcrhdz;F`OUT0-s5M^WluV4EDIs=}Of#Cww{)M1;gR()I9)rq0Mh1pQ zj0_B{tPBj{ObiU(pt1@Y&N8eF42MAd1yCKs!oXm`%)s!FnStRc=!`x_1_o)U-+wYP zFdSoGU?^l{VAu{STcK_T*&zjuV+~dYhQm;Ce?|s|HB1Z)vWyH2PoeJVU}gXvn*-7U z#;-u-+FC+w1Hi7aBND}IFl0i_SORLdF*7iHW?*1g400Q&?0~wL8C35uF)#$PFfjaNVqge^>al}{ z;SvT0hKVc;49biQ3~W%jM^HZ-FhllRf$RqDKb#Ad2l1mA85kr$?R#bhh6GR=h01~M zK>*3CvM?}wg1R9XYF;iA1H&{H28ItTko_<&P(3_Qc_yfvK>9aA#X#(RptJp%85ou_ zGcZI##Xpp$iTqR%*4Rp4r*I~6ocBTpuPqR1H(B+28K{jyN!u~p@o@&;UiQY zL`?zJkxY<%J^73b4F5o7E>av$0JUqN?%T+~z_13SiGhJZgqeZCnSp^}Iq04a76yi! z%nS@)L3x9TfuV$nf#Ds<9#C5rs{S(6j7LyDhyvZM!3t_;g7Oq#wz=Y!(KF2vE9VWMB|yWnj3*$iScg%7=^$49cK74Qkc`Q22w& zY6b=d2UZ4#08qQ1k%3_ysC~-Bz_5WCvVTgBiGg7$RF68Sp8}1mLr8W?fa)yJUM6M+ zh9*#*4;lwxVPM$D#K3S1bQUitZG-xUj0_B~m>3vNurM&(gPL<58ZKp^avKz0tPBh; z%nS@SLFEakPK4U?lbL~`mWhF(jtR2Qs)CV$p$i%gf1xypnhzqN7_@#-5t{x$cUVA$ z8621y7^;{c`yY2QFfg<;GBCJ-@;%f|Fm)i>7*vn2Ffc4*W?*1qVqiGHz`)?j#K4dT z>X$;@F2>5haGr^QVLC_ysE@+Lz`z3P`$OIS8LAE>ZG*&Cfx68X6n>yPM;I9xsu>v= zW5(TofX(?IQG1_p*NAT?0= zjf@NoSE26lW@KQv%fi6$1XPAW&2@r?l{u6?3KfTHN1@h1&0%GP?2+EYz`&3O^Suz^W(W1r zm>3vNF)}dpfYKDy9p9K47`&kN3xe7oEDQ{`ObiSepz;)I=3CI+HjE4mhnN`{>X;cA z(wG?-bf9k00kvsa7#O6O85l&MX6^x%Euj86R1M5MH(?A028ORJ3=FRs85kr%^#B6{ z!*Lb{hG0p!TR@93EkNx6W(I~$pn8pofgy^CfngKWeHqa3NM~kXa0iuR zP<|W>1A{fxoKK7l3>8ca41b|+>H&?nK;=NrVg~g~SQr?3p=NFdJKq8FnnWR zU~pq$V9;k_U^oj(YoLB869a=Ws7_*q?9tZ)8O*@I;03j-l7)fcJ(LZSss$0CGsKx0 z7>Yh_93=FTJ;gQe6z_1t8?_*+M z09}l=1JtKwU|?7U+PeVN`xlg-plo&~1_pDG|Ct#WDxvl(vobJfLes(<(A_goH?o4p zk)Zl6GchpygW5TbnSntIs-_G|=QA@fbb!W+pk~en-L1vKz_0?Ue*zN&g9cPB=>DjW zP;sbohLl#DG0@mHXiOW__k*ejsR7;L^`D7>L7SCiXz>v$rz`zX}*8rshPGg2wHb7#P}E7#L14 zF)%Pg?YIf5@1g8O1_p+Opu58u85pKBGBBus>TG5Ph9gW24C_JZ3pBn88s7r-t63Qs zRzckWa}$UL-2qk)4M$a028L*;n(3f12o?s0dCUw9a*PZNw?O?@W(I~QAWcxr$jrd- z6RH;^w4a56VInl1&oMJFM1$fLDi6B*3v@2SMHU8zJWzcF6$j~C4`qjd`oYW$45y%O zC;{bRkQk^81>Gga#K7Rh%mCgu0opqT((48qn*@y^vNA9o-PGcqtR zq%bfr+yJR(VPFUa_5Bza7^FdcM9}yN)Xo`DKb1r22nGg*C5#LV#UO)0b7oL+5SO2k zfx()Ef#D!%To05dSQr@MKx1W4v))5#56~DGXdZ->fx!+mHp#@mU;s*|pn9B{fnht6 z+rKk2F!Y1k0-(7nP&l$OFuY-AVDM*QU^ov|C&0?UAPFkNpl-1O&3Q2~Ftmg6B2;WS zC{IJ#+Dr@#6QJ<`a`#_QKb`?{M#CjW2Jjx$jVufd@=Od2{}~w=R)EfcVPRmX0rl+} zAZN3$VrF2lU}0d$XJBB61H~m1BF$ojKvO(8ooCqJpOB()gA%}q^DgmOI;GV)7{iWL&`QWR8u6>>B4 zN=s6U^%zv45;{nt5JkZX#i_~pc_|=8DGI1jl9HO1SejFU95s+=Afyl!4=|M=moccO zD1hi<5CfiE6iV{*6>{?P(osZl|;ztA*lniiwhEyQ$d1Y2H0sOiAf-VlEfq!HwUbuBrz!mlnPQ5O7qh4lS_+J zQxsA%6La#xL5eO0)?1oamRX!xl9~ceTOdJ1)szM5X;`)p21PU(K$54mBCTL*)zyF z)Yr|&HG;uW0VLoait<6}#R?=)nwX;yTvC*om(JjrlA@55 zpP!wZSd^{D;FywCT3iCp*9wUxB}JJ@pq#|um{OLQmz=7QlUbIkP?VaUnV+Xnke`!T zlA4!V3@QprN;31(^%xv;azHMN2RW@6#shN{$}>{)6cY2|D-~3W6)+u|lY?wH*ho+b zke`;u;FwdQ;9dlx;(fqm5QAf0UVbUaLCL8(ISTQh1fE)i5Cz*+nO|C@5T8_$w6?AorQVVhtlT(#IE{3udN-`2l6kvvyXO?6rBr4>kmMi4v zrRp&_78IoBrKE!Dro58Wyb@6ES4hsuEJ(^vEJ}gN7b}!xq$(umLzR@~fhvr&oWv4^ zqSUg?)N+t@U==7DVf6=tV^LyKX0n2NQDRD}f+2$=EIJkZ5_3}-97{{`a}!H4lNG>O zNFg^rB~>A%6qGI$k`s$kOBC`F%QDl!RS{mr#U(|h$t9&li8)wxBBp&&6m6_O+}OF-#0EwiY&L?J#WKQSdWg~2H`Jrff2`DqG8`Q>^HPN_NR znWec3E~O>O8E`K-LDMeCq@q-X#9ReW1#nOor4|>YCYOK$D7mz#2vjx|=iNEhz_8@&$>d#i<~znW^z<3{FM)<;AJskY;eIEJ!Ra z2D24X^FRe!iXMZrg0riOr;m>#gL6F8**W=;)&PTZVqRiOqJmpdY93MuU=uY0sm;qT zfrdILg%qPC^`z8fkh>HzOB9k5^FS(-^Yikc;RR9-Ev@tzoD&N&OA>Q3tH8-Xp}3?n zCsm<16&$dc$@zKsRpf!wIzBUs3sQ4(z=jmZ`{XBQGdP1B22JTs`YDGaJDDUVoID<03YB7W^E=bHPMzry;3Zg45$}dM#2Z|vE=Zw_kY=vNu+d$=o zb53ev5yVX?m3fJ|naR+^q5vs(iuD+hsiTIgRApmg`(8_qLkF4)D#A1P^PW` zCw-6y^7BeSZAnnE8Xp2m3|3$jMfo|HdC@t)AQN}V0hWb0mZXBiIlnX~MFEr+z*R?L zNh-MTDNY5K?8OSXiFt|XsYQAUt`(V(vL2x$Ei*4g0hZ5T309B68CpIInU~7oT$!Ac3h`G;YEo&s0=Uhn z04fVh^At)lb5r%;YVyHO&r7WUrEkmxj8$QFYNbMIaz;MHT&zmqVNn37O|dJ2m2vrL z3I(Nk$t9(btOItg9)oigsH}h$$u6Ej3@(W!@u{FHCO5Ifioqo{xhOTU80ypFf>e<5 zg3OZS3_a{}MTsS;ASrN@mB9ttbPcY|E6GSL&a6r;f{P`UmXze@feKsIVg^tSS730- zECwYuh4|DwaQ7f5GcQ%4xH2~>KL;dNkds)c5DZNLaDm+XqEvD=EsvA(xh4l&g@InVJLY6JW6#l-D!!(u+Y!4jh>Zswr6g08@xnGBYM1J}6s4x6f-1(;Vo-A_Ei=8e2$Jm} z-2ybNL@3XP6os&6CZa)!*`Cy6aDk{UD9SI(Oi2YbfJ+pL^7C^+O@rjjw9I4$XxB+0 zBeS?9ADRRqn!s%$BrSP~ppwibzeFM4oB>Q(fT&^xb5P?sMZto>1zR1YkPND%Qb8#a zt2C(228}R)Y9-YaxEUZWD7~f@VH$uW2h$B1Ndb+LxI%j_t_ny!7gq&HufQki7gnUC_t?sQVC~l9`xXlv$FQ zoR|X+XsA)e3dJRv$=Q`iJsLd**F1352JS^b+2B%%0g~R5GeCWLaC$3A1$TasI#?jx zP*G6!$^-jBPeCD|2-H(d%&P?14r-QWq$U=DyWp@O(^F6g$yb1M(lSyNP}<+>#R{+y z6L2A=11i6Yixu1q^+1}^Q%jI)Q&3Tdp&MGu!^RGa;U*XnX#!j)sNn%_Ey0>^NX07L zRAaEIsTG+e3W#8U$$}i1TAZ9%kO~S6Xox|E;y^lz6_COc5`K`7FGey89;8r%O7ayz zdXZHyxE2-V7g;GFTAiSVQVD2C0@Cb&SB=mHDyn8kqZQId$;&SR70TeShn38bo|qnk zo2QQ}gIi`^3YbvvhcU=-MsNK8QioioFXdOFjqDBmEMX9M(sSIw=l8(VWH90#UWC18o73JsT zfU*ZDM!-FIJqGvGywsw^90vE)qTIwhXusJ2m1~H~HDYkj$xlkmQ3wNN3`FzKJs*_N z5u-&AKDdz$6I4L7{UNdipmB=)(qi}^6N-vdP(CQn1C59%fW~q37~JzyLCGSm1YN8s zGd%-Cuq0mrVm-XU2{i#O0d8rc3Bt!=F~mWgzNGvLba7ad6I~qE)OF3LNOLAOnrOW2l0*9>0%=Sq8C(u6rNPCqr8c-E-V}$f3QN$Sr98L}%+!Y@g)Idl zq)}2KvT!yQ`$3%*a9;+899Cg0sS<7vD3O8tI9POIPn~eBSW+ll4lR|!#c`!nxB~2{ z6)ugMVnIcH67pavNC4D}M|cJ#k^~v?%ufSX^`MymRC#FkAEXphGh}EMR6r|a<|!m9 zp!p1}DY3W&T!iCSfjoOqo{^cHp^yt2nob1G3qZ#6L9;1aMQ z9FNL^)FM!+$pB|5AV!Eiq1_};n3?7gQimw^HOsdJo7-!8tmggSmhw& zKc0ETsYN9Wo}jT>cs*~(;GJ3t8^11R-3rb3hQd6uzO(47~!95aC&#@$5!4EtV3~~;#D5&QEnzDtY zX)Ll3E0MLpx;>aOAVa|YL;Om>8o{$H3O?X|34@Pon5&P1Y6^o7C>4Wxy|92_@JTEw z1Em63Wc#Eh7NKS*k*ONoaUFMVs#TVjzF#-;% zV!jQhdo%KLQx%9%2lhKs>k6lVV1=M144^?IP+9@S9uD8Y!-g1x;fjeg9AvjbViG7> zfPxFwxdsX2aS}*cAt^N{zZ_goW7P%jVS?uxK_zEmd156b3m{vQ3rexzw5rG82VFYg z=jiLo;FnqqnqPs;ae#_Ezf{mnIH>Jbj5f9Ems$?VRwao^paDM+AME*zM9}mmXf8hm zG*#=DuYfdUpa7Bu&nN3K_~k2r3KQrW6$l^XdXNOjM$lL{WTgpM4m_=ZGI!vYuK*DQ zH@J%ts!(PLV5*R(2H;|_)-!0x9VQ5BHiIVtU;>EtGLjw8b~4&hN|7XxTcZ$R ztfMEOIEBuNA;))dYEfBgQL#c|Sz=~RVp0xhA(3Cc0(kihx@ewmX4P>_~+%sSAs_U6SF~?Codf|Vw9N&8t8y5tN_iFf>gm2r9h^~ zQd7WHBZGfIY96FM1Pwt!*EH!dKt`e5i}FhgSirN=3g8)Ph5*na3O~dujR4RLIH(|i zR>TS^5aU6OIFK-;d?%y|Jl3Me5Rh05Ylec0)#Uu#Tu_mdp9eDzRz4x+e?5kP)FMzM zLWgm{nNlG?4?a7L)GPuwZjdy9?FB7@NzNux2gpxJiN%@8$m>7y3sNC-KS)M{6sDw> zBxdG-s{4#o*jf=}wHf(&so)W1&~g>fBrYT(V4g&FI8u!ffTk@c2e&p*K1Wncr09fH zw*i^)CCM394A2%Bqxo=A{C?ovK&PR-1Ptr z?3NaQnc&7?Nj`KnokC(BEV+ZH4&b^=^3&6EAdV^ng+IuI{50tFIzvEFW?l)nEs&iD zYFxq=q#@-vP+Wl*u7TFLfwCEBT}2UO9R*}S9=i4qwCpYsy09&^BD1)pSdR;|3MDhI zG*zLrASDspG63Ziuq>#UgqG-#B~_sH1gYQ^Y{?mkdFiRe_6#tSli_Pel2R2QOSr)8 zX_!2;69^hJhYEpRoemBPr^F(KP>}VhNPQejaF8qgbIVGf|-!zAz&NR8N3b zcO>Se=;s$H6s4vWr50y^YDooX`3<)s8MKxVbw)WJV@esHY7E7C3<01y1nA-vAJ95% z6cNY@2WZ44g4Sput4EQ|%`YxNH4a4@vIq>P?&5sVe0N|eX#FZE@uAFhF@V+#fzy9Z zVo7Roi9#M?z9usdERmU)oSzFytWYl&gKJXIa?eCPuy#m+fLP0_kXT%t4~kq+RRCI+ z39=PlZh^`=q~bjYvanMj5tOq)%LsE2t3osLic7#VH{dcRvlw-fj{&L`6!oy>wn3?& znQw)p(samrPssWxUC@xGLwX)4Ao7dSL9Q+?Dar(|UbJEeN-ZwUDJfRSEiEnq@k&aI zKuv^vST7VjQjncm2^rD=7h@n3z%!4?<87dIexMbzAou7ofEHRo*BBM#XM!i*p&d_H zNPsFUkh*fvwuk(3%@iHjqBqcP2hfHJ%@l|{e6%D8wDcG}5S5w&S|tMtSWr(896qVA zaYJNPU;~hs#RVspr7A$n2nEMt1~k5cbADc0PG)imL?Rxh0yY6vtj7?XSg8P7h3phx zX~lrL@(hKi0B&KqKvs>T$^;-*lc1Ua8t#IxGXc$Hs}`dvi1&ppF7QsR)Bu$|P@_Q$ zia|pMX=!>eEij=xbP@PEv!YZ;VTwgTX#u(*sG$v7`~WItgHscWk~0+IlM<7&%M*)I ziW#6Hpn*)#AfFygASJUX6#Xi(qWfFhG70IGcf+fXFF6Q2~@lL2JGtMkA?( zSJe2_g9eirg25Y26jD-)GmBDFK-Co_8ADbKfE)?hhys^~E{B8kDsakH7MG;vg1msD z7u@H7iGsojF-RK>N~DlQh54l=poT(8z5j>*Av8;bG}9y@Qq=gI1TMfcw56btS2J$*By%sU`5;1IXDDX%Ri7)GWydjnsiW2dVg>OKwW? z!L!DR#R{+`sGxyLP&YKS2$bqUOL8+(L2IQ!Z4yu`0!b;<3>4L+1t0@K1AK_3QyT7} zo(j-(qzQI1R#l(@G!$i}1q$$l1zQ{ulnN@TK#l=5Awi7{J%-?n%(N1Q;LHjIm;91q zhT!bX0)_aboW#6r@Z>=;LvVh4ZYo1?K_Y0j9o{w#E=Wy`&xRFvxp}F%`FWYi#S9?v zYzV0k51OAqW-BD;=NF}9=7H)Bm^f(1Q(g(US_ik$K-(SQD*<4Na!YecG7EB2!A=4- z^YWlJDa3=SGN>|8PY7B|D@h@52O8pp8UuD*a$<2RH1`!NBo>3lFXKU39Moxng%V`1KyH3KXzUVVUJT9Jpg4rhw|>{4@o;;SK7X zf*Lz1&>$j84}7IO*onmo&|zWNavG>nkSZTmli}#OK}`TK%w-<(WA-;PLe&@M4)1JuZ-P&`uvnCloRW5?@@J zo(>w(%+G^JXQhs9=oc4{7|#Q`es7=pn&SU_3P3c}VcEr7LDKq6T7z<}zr zVrXfOZI2989#sFA7Niz21ed3#Aa~P)%R%eDQ$fS6kliFnpxp_O{UhM=3*6cRFE`R- zz)+l*2-*P#RtITQ>w>Z~XrU+C<{mwUU~p72gn0M|`7wk9xw>c{ z`Q^n7A)v-Gd{+^ak7#H!gk*r$wddsImxJ;)Xag2#djWX3!b$-w3z`4~4`ZaJfTpit z-P0t{tO}^=P%VZjgUwNb#+Q>oJ8OzkbMwnU>s>*%fc8~^%*reV_d7vC5I@6q*=B;* z1(#r1Ar+FDn+gsjm&B4(hLC*7&N0yy625ndbOC;y#wr9(37z(Z%0h<1z|!EQcj@4@SGmwB zEr`QFlP8c-2T)5iH?aad-35_L1??IR$%k$%LRt<9H6PSQ1WSWf+!mK6DdeW+mBL() zY&po=umKK;(MWy+D+GHEv}6(5e}EJVU;~Sxwt>nj@NkPED8+*{fZ`79?~>HqVjWOR zL?Ja3G!+4EY=S)wQd0H8(S@KPSu_lLW#JOeyy zqfnj-nw|xZK_J>4&;}^hCFc;gfX1%Cg*v2+&n$sf2{7|Pt7vhRW(YN)NG;CHNzF?J zW$yem=x7F-0#K6#Dv!4@fY1i>TuDAS?<#=WXy7n`Rnp+83rOP(+BYfB$j<>ceL%xu3Y!K9)$`UO!QbF@9pcDZ% zhzm6CTdaU)5L7f6RBD18069wm9JS!_VQ4M@$GRR=aeiK^LP}4BsAxgy$9TIb(>Od|o zf;BZj?Gf+@h$2H+YEgVresL;@0cqMXgyqNQl;);dF@V?ZLP!O0LJo%Q;sVQngjk?^ z#UQG{BJdSVNMg{o0YV!hZH1@iAWbSD^Nbjv!>r-?MWD$XP>V`IAJh~Au^2$2;M!Ax zA-pKD0JJF^6grRv5_%|NCHVz<43W^x7YWN}k@=+xu*O0LXvhdOypA*+mzbvj+k6Nr zZDCu3Ae(^{@(WV)^thn2D9Jhb#i^j3ut}+Dkd1Ar;62|+o3+8Vfu@X-K-(C=yL>?d z;NYYS+U-#WE{8#L-Fgb1X$qD3rCeY~fr~Ei3O7g!D+c8f@UC9c)5~N z6;g`w3ko2^XRy(C&=`;&7hbOwh4sHQ1qhzFk&0BQimgGSlo9SaI_DjDLPLBpFl4DrsO zFk*;z0k01O(U7wY;vpmEpd<<2y_%W=+vURmlY)%cFvNof+Zf_KQgaFz;=M|93lvK7 z8RDS_A;g209x=rGg8CNQAcAwD3rs5n2*iXk3Uuz+SsO7inT zo%CXm2>4(F@RoKfhWMbwl2j0tTAW(K5Dyud0?pl6F~ozrT?)>i+B68XHw)x*m}p{7 z4nsV+B?y|kOf0cth=*1nkb?>s;=$=3oL#LL;z5a4A+ZS5N@Yk?uu=eT=h0C}QULX; z63g;+6p|IJKoxvZPG+i(LW+VFXl-3dqK-nUf)#j|sg6RLf|WvAenm-9eu<7kx`LHL zdVWrtjzWfll|n{-NotOcLZ*Ths0W>ysH2djV5N{%nvglAvZHSRYxID!Ac=7zbq9r8K|R>uVAH+4@w<63Iz&Q3I&M;i8=~}3RVh* zrKw4&$vO%}3RVh5`MIh2Its-KRtm+LsYOMJItnEURthDFdFlB&3Z)8G3ebsp9fdLl zD}}Pm75G+V6D#-*NE`gBBW-G>`V+%&@S%0l0*#g zeDK&lc9ZgpK&=K$Ek(&0nJ7^Kb|UDI2&BLSixq>@0EP+0sfh~Mtt~xKdJ63ls`6^H8D^ELfafiD`3YE@+Y*HSF_K(y=6wG|+P2 zq@v7Z6qD0(K&cE=@1SNtP}8lr1Tz%UN|Q5+Gg0CxJux${I4QpBUmugL{4TdTJYtjVu^#yJXD`zDUWg!i}Fz;C^t0)bc9kO*2)ShiC(%w zh4V2ADX2t2X;DEAii@EV#n{3TCI=2K999(I_INg6>Dm_$f%tNd@&OFl#`F40>e;7R4I4U>WQ|3+hl* zCW1ns0NK?Asfo!M3I(NUX{e$_r6_!~TB9JR6eS`G^25fZEXHC@=EbRr#TlufMkk^bR-Bodmxodj z6=&v@rJ@wY*s4tIRX9Wxz2+&-%SWk9aAl=ptVL1@YGbP;71SR}Q*T>;ub! z8e6%!pt#5_NG!@M&d*aQ%>ys6WJu00s05GvF(en1W)^Gg^Y9l7L6h2qTg zJcg9S^z_ssh7?ejF(t8tAte=5#}_j|mO?S4WG1E-r50xvGo)muffo#wD1Z*1WJt*@ zU`WXXjo5<@24zUeNoRmfT|*a&rlvr)b0k9!$SMF$*=FYFVNnJehr*?(G!HV;NYFGS zg;>qY$w@3?NXai@NXaiv0SGV4(n!0_|D>pZWxoE+_)kWuVy=hLobja)wms zAV4a(KMfrO099_F0f1BmXpcWNr6j3{AvHINAvL$4q>>>uPXQdvsd*_3;7&4x1TRF* zP6f$>H-=#ZBLjG}pqK%&KaU}`B!eNfv?!k;wIVquF*BC|GOLxE!jP6&Tmo7+od)h6 zf*P2ac?@YeMGR?qB@AgrxeRF~MGWbna}+X@p`Amdg{SESc?^&t3{YlFO<_ncN=*dq z6ot~DV<7WDlTu*kfQG#?R8ts0vzVZfrqY~5FdK9lENGPz_z+@HbZ4aGr89u~s2Qn= zWt9rx9W)F!llp9u~1 zOyp3{1hvA;QW-K~p`MwX$B+r~EO;A>LT+LKXt8uQLuPI|LuMXig==O~PAUW5SsWJV zd15I9ltIP~L8{U+^D;{+88X4E1{pH*%2JC!LzCc00v%2X+7}C2pNNnuEQQSYLqY>I z=?mH($^stYfb&2J1DOLJivjJfVt|Xnc8MZHP~|~9ur_3c&{^nW_}DpU;U%aco|j(C z0$uu-0x}W2jE%)Hrv$+Pt+g)7&p`-4Rzu|^lS6Uc8~I1Ff=v9bTD_ zG^mYM+@Wd$O<3hYOHcR;MD$`5RZD3B9@iihjRf3{q!N#b*$kk)Um$Olq_V*GTOkWV z_gXQ4#}FWg>=q-RvI|}y2wE)*Izucqg&`*|n*ny>3JYj+QyO?g8gzCAXnp{c)Ikf3 zQdvM-f3b+>G34Z@gO{u4<(DvkM{4vKa*9hpII|>|A*Zq^r67+XH!-;=KaT;lM1UbT z6Wm?`)d-+Nwu>2Z;oE2#a`Q?-IH?Fkg7oKtRxA~R7qKwpmNJ0Xu0cp$NcF@3I=B%u z-kX(5XlWg&*^v(&jLwG@l8|v&1?U04poP@nF@DGy z@Srfx&tu5P+4=y@Wv1nq7L{Z$fS4JHIcW^}1toa}c?^(+ia8A6LvcZg4Z?y160SNN ztQf8YOYIF-fRr}Dxe7f)pew>@P60zfVo@TP0B>^um%ph+NCI%TfP8>GV}Xo-=!PrC zm17V}k-R{R$w8chp6yz6x(tH6Z*A+8Bnmfpc(}D9Vbnv~PJcR*PbumDSQt)<71~3UZLXicOvS9&( zB7qQ0$;~ST0InPj>nwtsgJAyEMAbTc38!C%Hi}G+O0F@y)^g_}fE{#Q{DX9z~AA)9%^O93R6$EJ0Hu#t~s0Ua; zv)>FTBA_NHLop;y5Y2bUOjvPFN)bbG4(L2fRSj4-1a^r8^hOMZVrZpNoS#;r0BLtJ zfG74Dupet#T#%W^P+X7$ikRX8@N^VXh5_&J!XoSoI%5KhIJnJ+MLak^HlQZPG}0qZ%BEKZL$(oaTdibKn^=95%q@aT);LUysKLFnOF#a7l&Sv;yk%V0VNo zCm+xd9d0R{)@BxiG98vhge>6GZ9Gd- zb8)!_bRYsq9-rB`~4kx1P+@6U}qf@lE-Cx5co7?Cw$o*SqV;K@^f&NMv(1N zsVNGe0K(zS;1bX>9_;=HuieIFFK9J44l_f8JaNh7K|3u9prnG!=&(f4L^^gig+UMJ zgX)Lh#ALvLxRuEeiEV_$Hb!EbAhAu6*k(vj;rN6qBGqfsjTH4A5`^c$5ROr(87!v}26{ zL!=lY1ll5n+9)moHPcIyau`aIKpoYR)S_Gl(Dn?Lq7?9{P!M)%Vu}KS3vWDwB@x{N zutv~!1^8$VNC8*?TI?fKfHH?dQhrJ$LI|{IC>^{8474#ezX+>LT4_#>LPjd6eT-GU zxFoXxG=B!SIVrI?72Fj@h=7(LA!!DUA|P?WCpRJSOLTLPol>G(l!K53UD%Y0Bn?{L zfh3!smy()SoSK3Vf~=(lRnBntKsp5oC8;Ty;P^ul$xX^HE=J<#K}Ja7M!?5jkwi+0 z5WXp`k>VsjDF?Km3Sn}7X$i>PNCIW4pwktR%s>nb zfN!HgCg<#kB^Dse1eaZCT#Vo^0xgw+#~^Zk zE6PC$)S?n3zZWMb<{)_s)QQBF0l?yz=^xT-L%0ld)dvzUHxYCZS7HHD5ESR32a*LB@2H%jQlw}o z%>k7+pql~FNN(4Au7`KXejRE83eMc~mcQ1_?=bZ}~VX-;C1 z0(1_lqzJO18q}R+C@BKh-xVbcrO>IVQsiOSQs~rFsRDFD5D~zodD#r51q`szgfl=p zWf{uK3yMk@Ak)TBYatxaiqM=?s0?Iq0wMt!Az&!aOJS(cEzU>;ExU*6tc1F(66T1? z)I5fOqI}ThE4rR3x?!nBpnKq~6ku1tflu$yHP$ubf}HW8>sy?jnWF1dnqI6Ml5eGu zQBqQ1rLUh%v@a;iPbp0fr)~V zft7)Ywt=C60T<|SQ{9lF#5~Z_0nkDEUiqNDVZh;)MX6N^P|7ANzbL(=G}j?LH!(9u zFF8Ngj>`vHBk6{uCgxfxI2I+Q=jVZrj*?!?2sT4K1Mq%^)VvbikjjEoEAXK$`UN?OnR(XWG+&%rVjCLbrfY#v2XcE_YLTvM zUUEL@Mm8%2i=@mFu7DiS)pNR_fq-Hwg}eeVx7gOm8ngkkC^5%YBTqrmR>4rynkzyV zavpvO$o~QPpq7h*p`MwZp#c}t?XZc+>|)TVI3@YT3dNc-5QHU1?b{b$YvKTa&B}Ms3iKPml!&V@- z&nD(1=YuW}NKpsfQ3YCquaJ_eP>=|k_{{;Gafg0;tRC2)Je(#KE0ACmVx%=C73(ds z$ifP#IjNxO5$Nex$(i|iiKR$4&SF&yx?M3RH5sB9bVn@K%VUYSR5k^4Cqxp~du7Wq z^OAG&6-p9Gx>>d;u~?xJeuHd2=*n2oy|P7##fW=l^TA3$x5}oM=B0qtpu}Q|0xbFp zic(WjLH(A@yu?x*F@PR(aNWhA$xwuLTrmi~PZf0WEa;w75DmWF6rLh;6N@tw!R2fo zNC8Y7bjKT90-^(aZCxT*5rhdAPRmTrNG-~TCM=LFM5Guh0#TG-lnbf@GV{R-;5@J- zc*{U)5m*Y!28+Ye4M+=&jUoZH0Yx4v23D7wnpd2doB=v#QZ)s%2^q{Q*5hJ`OjXE9 zt;{S1-4IxiU!;(n3ED^m$^o#YBl$$BQB6^RYX><4g_8=ZUm!k)GQqAYNlYruNleKv z0%?GAU{X2Y00#A;62U^Car*r9e1+o7JkZWR9tSw4t?xaKw=`JUT+@I|+X*fP{p2+mI`O3h6z zP6SFwpan-Jy3ZBvbY#xc&S1O%q+0A`FYSwgA+mb_QEgR^#otI z>%tK42ssiD>=)1`q12*8g%tJDyhPAe?36?XxIEZNpnxc?%r91mPt46s2k}5tV5y)> z%JNe386p!Ek}?%C5KO6)Utd~sSCP_036Y! zpjZXXhNk9amKK9*jC@eOFG)-*P0h(kEC$_{oROK7s*n#drv#)58ikbr1g=y8bf#@?Qc)@>ZRDsYLatuUXYkEW0UbsKE(sJsyVY_* zclLsgb|@)I1zjneSeBZe2sRC*Ga0-_h9q5}d;q<`m%%l+AT>F&AQSBH)XLN%gq4Y) z8XXj13I&PD8JT&Bki-X#3WfOO#G>>>P#7tIXTpmT70ObpK!;`KfeZxu0W@!$lUkI> z;E@kH0Q&Gs(2d#(PN_M`8JWqTJuHc!VDL>W0_QM=!;N_g#rc^E(93*5$8;uwaxiE% z65`=RaNg8oa7;?ftjGriHt3+f@*@1Euq{#H5@=g;a10swy9R*iaFu#Z_9ISj-UbR0JxPps|yOhy_U4=YfWR5{nc{ zQj@`EBxj_iCzk3#3#nxIJ-?tEP~m<7VKZrdH<1r=-T`g6fpyoWx=VH&B`c-A@c!OIeVUnqCUZpM|A~ zDMcVJ<|cvLT(CsroSFlv;T$1Fm_lL_DCL0~2(VOxQ>GYn13OqhLK8f7W9ouQ6*D;J z7lDi0B2YrkM|g?BCo>nE?TQt^p_~e8bb^jA%gsy%o#Y0(1{`$gVj}1=2?8o%wn48Q zP6RC(gDf#hNi1gY2SqVx2qGU;Ij9yhfG-?Q1Q#BVYly*-3%`IETzw&>Z%|Z#PQxtD zFM@V3lJg5d?a6%5##GRygrEX5HBSM(+ymWAoJgp=#G=m+HK{_XuOfvU^~4m=i8!EI zJSD#>n$!}L;6(?J2W9u{l<#GyVX z6Vy3MQBO?1-il->@YO53sQ?fO(I0#Vs`@6NKgTkS5gY`1ju%f73oFbQXO>F zF{qE82nw52h2+GX_|&|V#F9iS&^^GQNu^8$&?!fG;9?tG^n!0~g~)&^lbrnI%#_3u zWch$1q|OvWFz6uDlFTYl^9-dSTgu?Ckd$8nu9cB>fRc%7F@q~;4h&q_DS+-ph9xji z5QA<)28R-;!3fGCIhlExiJ-f=A$QDzvkFMO0NM{{a0G2tFG>V86pIxgNiwyV!7&$9 z&K7|hJm5PBL1`vcAqiZHfnz^8vm{Xum$Lkl{5(*L1FIp)iJ29tC6F?rEVT$c1`l=? zF5^J^qCty3aJdR}h6~uZVo(tZR*B1~6wo0Ji7DXb5Dv%X7UY9H2wH0d=?~&E3|j7i zRYMXK=z?YJAqP{7-7NLYTu>)450?*fLFGJ-09DUV0KEmJ zI{MgLs1ENBff5HeL~)q|mc-#0P-_Ex19KWKi&8-e8`O4BNmT$ZCB$V7sHVmpPf*W* zyO*E_YzgS>L2Mp_`y1AiM0Po-6apWp3(hj&Yok!QJn&;rG84f~>Kye%L|Yii;iQ-Y zF5eSjofFi~2e!TkSbafJenEZ_sJcijg5AlS3`wW35d?5DOioNmR47i&fz*x}i6vm& zIpBsd==x?zdtDt}O+aZL=)xa!$k?Gmyaj{-y2ClXQo(}38Qy`)%u57S@SsEjZF4A; zm8Pa7rX=cNQ3Y*pr6ekpfO?DIg?mMbpfUF#7#no`G=}MLBk?OkH6G?3(2Yu<7M4P) z0&=e%x{C*;*AD8*AUf-yqnjW-anLo;kP~K#!1q7r7nP*Ko7*r6=rTon1>aQA&M$>h z@Ga0VSx7CV5TBTn2D=OzJSqno0xgBtISgpZQ&JV;K{xV(`iXG4cu=jBk_u^>7sG{N zHbAZ;1|5e`1nLTdd*aY`JUC6nBejL#niD~X(ZTy+$UQ1_7pcc5CWDJ-xL&BmDe6!O z{2_op0C4C9`4}`%6`xj=SPZI;puU2O7bF(tgIdrq*TN-WgM)C_!epR2a99ZQQ>p?i z_;Dx%8HX7cpo@PX-QJW;(1Oh*Sl3@2)Q*R=G2t$P+JzEtIBbI|MY=y45&sA~)AEz^ z6$(<*6LWI%i}S(v{DLwlyjks*2^vQMpJ$%P;F(tfnzN}&2G#9}3aQ08so?0fQeX&9 ztpxSv^Gb>m^HM-Pb_LK752$!Oycu-pC%BmksY0RhFgK_t78IrCrDRrtsxk1vY$c$M zEn<`h>=DqY1Za0sCa6UV3ulECb?ejBW{}pyG#MpfCZh64LU;(RKq}L z5DJP?A+0~~J=BQ``AH?9U2h7ddGIESI%ud1)`JEmsFYODdJ0f86? ze1uXdfCl40hyEbk2D*zHT;66DfjyE7?t!BO7^v+B@(JiNIZ*FAMIEvUP>;a{++Ih0YyFR-fFa7Omb0bCAen= zuKqzzfi*ioM}LDFrXX`c$pRExSUd?j={^S~3_#N!pmDL3RK&nHXq_{-MOa$Q;O6P< z;Tq)6;G0>LSj6BD=`Dd0c2a3^aw51dr%;rdn+WRABq~6LbHIa$@Eni>6$V{l2FaeF ztis?AaUN){IT_rkM9w?;MW6xD9QD*(P-_w#oZx2h;mvsr$m1Dcb|!QX$Oxa5ODc2- zvj}_-Hn?o}SAg7vT?y(ZgK{Kjd?_E)*#wV=f%_tmo3I^oQgaV41f6S0Dz2rGrD zP)Gz_$&d*$H4IX&B!dSVQu9g@6~JR%dJLEnpy(-0&Pc=|mr|4p?qr04I-{WB2T-2_ z?mDn0P_D@bwJ1SdrQ%FT2NOvKCIm_y;B8NEIZ(;~_e0PO1Qpnz;ZD%zVVG{XCQuIx zVh3m}5qXdXt|Sp|o&uz#1htHyK0wl*oCxkLgOVU@+6it1in4;t642BYVvaBcpE`&f zsC@?w3k7J;0wRIh4~In_HaS?Q0yL7B2UmdPIdH!cE`j7^NXs0X46KU*%EI7M1g;3h z++tA25*lJi65vrNP&7ljyKucoRzp`>rR8Ijg!ZQq-43V~Nctfc&w=v>R1%c(Kx3-- zQUb)os67#=b|kZ*sz8-#320musshP_kOm6e>7b+MN)k~s7D{qQ$#M`GSmOs%7b3Z% zYC}%$Fd0xz1(~M~6Tq3+5h^g!IzkFxQb$&WC#7R5g9MX$A}oDl`WT@HBb_6pa3yna z>c%t^bhs*bLLL?}5N9NU#`d5EpaR@TaF#_%%m`ai6F)*6R}x34z)ax?Ia~=Gp#pdM z#^WDo!Y$6sgZ7|{uy`7(2s3p<5;eAv1T`3;6D{hApw0W4ka_@=@)8x&GV>C1z_k%% zsveQ0!E)d+HE<-s9g_&3#(`8lkhwnaC<2n2s>JkC&`cmPYS5wsbOxnD8n~VWH8CMw zc!ax<@;WRD!0kmu0frQ4E)jGlbwMVmsR6oy6uedetQ9_43A#2S5wtflUys4PC^I!3 zy!RJ0!veYn{O~SNDGlauo zOe>|RXCR3~ro1yzy3)|28Bn^?pc5JpUFl2(*rYb-s&KG_Kr4Sza~K>;LDO=eVfB)H zl%Z3Y1gIB)W#rT?GdZyca$h*SH3Vw@K-U;Sd&i}S`7&51t(3tPdE6ML08|NqJ0+zG zsX3Xspotb(zXiO)4b)Tu4+s_If`*ntz|&&M;Jd^VQxZX^_UkDGl;#wtDu6pwXv&eT zECmgCCnn{9r=1W}Nl1=DQ2}<8LM3Q3Mt)AB9*XNR72=Txcb)ObL$fC6I^M+MRDue@ zgWKRqUPPx1?AB5SA5SO9h2)M3u>1w7M$4N4mizXl5+40ydM83~FOSXEh*g zN+>5Wrv#)1)CU1wXs?i07r`>nQ}}7b&DAmgN`eC?pnx?i|%)NK^n#M&=hCUYiKI+B`Y22sC>P9oT}1 zfM#w$MRipsq=W*MN#G4C&{P1*coil2po!w5WbkY^tmww6(m6jfFF7+Mvq&Kivd#rG zzYB_hL};Q{0NtJrns)bvu8sm1_uyeo@Vx<`5kAD7>7Yh!UOH$AGq}Eh%oHX=>`2Wk zv0?}Sj}EWoB*~9)Gxk`@{t|`b}bmyGA?C^nM`m(!R2t!%8cSnNFvM3%S_Hp%)w=KKD>8_92{6ZhEz$z zGPOb}G}RGdJfUzy)bm7}4o~wbpjJRGXpItF2sZJLGbkYmI|Wo4fzuo~pFqoXRL%L2 z^*G@Ec&S28Dd?1{R8X@OydVX9r#&RBL8CXY6b%_g&#O#j@bmX|3UX!0fzHGx=4Gb9 z)`6*}pstPyNIbk2bPux=XoX8LtYzX?np&2qPynh5@+#r86QEUkpk-bPiO@AnrFjbA zrA>%}*gdhRC{Y1v+C`xxGZi#f4;sk<&u)O0g@Bj5fR-OaT8p3y=3t8vp;;KN0@fQS z24!x@qORP;Vg=CH0_47Ms2FGgUJ`U7(=Q*o{0qD+4>o}bwjHV(WCC>90K*i>dJfQH z1IU673x6N&`LM9?4scnlwTG7{k!uo7^$39JYbJD@p8tV+Ig>Lb+tJBrg`Dxkd^XyQVdcY~ea1I|OBgoTnQAyqW8#h@D@GgI=5 zioutnDL+fdUS}VsPsUGVTeU06?xxz^em6%1Xe)vk;F$ItTeEodf6@MJSyEP;GCaZ zP?VYk?(l(nD#(kU{1D6MAS(zVD-4T4%P|Ua605+=5kc)y(2-}LgL^;! zWNW@cF=&~yLJoYcA2Nvm8jW&G1m9z?08xjj5K@^S)CZ-4SJiN0<9@8O)mv4g@pEdpf`gg7J*8!JkSEhlEfm=5Cdoh zDrk}nydE+hyrLJBUQ^V;>k1j*%XL5_dO464Nl;IM79@bKi~vv5WaNXYO>pfFP7!b; zAw4wsj0?niq)d&h8Wbd;-Vw?SO-d?!k_H^@C=P~|itrI19Oi=-f`J@A+&Hmw5k_ewv@&pw#d7#(_ zEuDwvXHZ`xIX^Eyvmz6;fF9IC0^OmS4_#PZ0xF+D8~l<}iy`wZ;I24mE)`>ipB{rh zw3DcyTC7l+sE}HbSzMB;2i~ZbnFmTO;AE0n1u_)e--9fogQ&|Z0mTt$1$#bdsb_9d zYJM@KkydOEuIWIF=u*IKa8Rg#CZa)0@IWIZ3;|Gs5X){s7x_U%!4uh~;9>-{t_8F; z2sBj$YVCp6NEGF#7o`^GGdO|Ue@G$nc5oqKMyv!ad5r9~1qmY;kUV9H-0GVHu2U>Ci znw%}lge<=Ut?$hQEyMw(io~)^PzHz0wt?CcC8^-WeTfQ{u*D&9BViU1E#Rt;hM-fCG&ML_-!LAcoQBI;l zZek^Pl!35f_y8FptCLc5z-zLDLFa~pdM%hM1Q@{e3Mjck$EAwl#U8l%lcNq9HGqy` zfQl+u`2}jog4aQm6zjo_f$ebs?QqFY&P)XF3<9To@Z2Iaa`hO3OW_+hK!YIATg5>o z8}_Y`kQxVE@1g7*f$iu?NmVF@8VMj0aHRm+pak83s|#vpJHU7A>M;a? z(tl=Nat3J8g%yK8Xl-?IX-)~q@fnGrbs<&^A^Am+ogeVEgy1X>?K8p$QbC55Wfp@9 z3~){XFPZ~4;gP51AnT6v^T4G$XxtezeVLkv-0Xn(SC0X{x=U4~D8F1YMF(^+Noj5# zXtyI|HJ4@zk}CKJqN4)l@M2mfc?J5Zf}Bz zk}#979b(-B*0ckv(7*?FCxaTo*s}qsIs#ox3mU@KDArVnM_GA@JU#pdJddGQ&1L(!7~`B`KJKh6$k2L!uREYs$^J)5mZKj*P7!~ z3##5hBT1*(m{sO#&i>*Av8;bGM$-SKs9e>1$c)ecz+5wAVJ-AP~!=_<_El~ zC>K<&gU41tOUt3lUW-vpfR{p`ASB)hXV})tB2d0SSz`>EGgdE!4Babelz~od0F|vN z>Y$whMQNGInV==BiJ*`{9^)t7Ku{YVJeUO@F4sg~I0On>a8^+OHKtQRc_|gVdI;1X z0ks)HZ##dxQj%skK>0(f#2T*HDd1IuTKcS_AE%}Zo(EiOpRtIW@V zjS7P5=OTr8(Bf)P;RGripbai?K){BgVBLRkMO>s14>ljl0gZv>=NEx?zJeOckXc_8 z74gN1p!1wc6+p+*mlh*+b)ZH-R6}cgP}{sTFA=mM6=IEFzCr!C&@yN6a%_l~!Bf}8kfqbbP~#xhLF5w^3gYu&!{4A{ zE-e$hGY9O5eB@?KN-8XL6d;8YXq*u=C|6lp4BBI+P^kdgkpf|ZYAc0!$N(|S+8jis zk2XaWgW|2bU;i=X<`njDF;oa5_1hgdy3Ji+4oYxv zpFtXHAYDjK3CpiyfHu(8Gr^5f$S@h`KGD=t98%DMpHhb40`PU-E}6vzpgUAkix`3t zRaSgiew7u28+a=#qU;961VjueY7(LKTON23XG&&q0c0dqk0BmqYZatNX2pP{z8Jc` zGqLFKLOm{qc-NvLP^G7iJjfRxTnbu?0qIqyph&@npGb&Z$aqx_Y>)$Mu!62!0FO?B z&bcc}EJbW@22IRb!TQtC`7kR6@Tvq*!G&uzKT7&9)+0g#Ja|D(5b#mg!KI)z@6cf@ z=fvEkRB&&&2$cR|3u%$I7${UKz*dEWRyQW+gEoeM#%Dp52zYQ7S#e$>=qLkl8#Ecb z@>QWyArZ{QYzynbk_khUe~=$^)q#t;V~~@-4`@#b`k*X$WV;yN%K(QHSd76Dyp931 zWeVK(swm0FCgcw~fdR7IvsfXqC>^|V1=O1ajily5hy9AJ6hODYf~qftOwdB!lv2>H zKhQV}D9;sx`iUu^;b7Hb1|N0Up(nr z^>ZRj18mDOVmJ&mQVcrq0aVsxR=^cPht9yVI-urPK`Ch2IAl3IR1z|@t)oz)o)4;< zGIPOG+n`etK=Zu$3Y8F<#0rE=T4tUeLx?(Lp#`WB2upb2fk24qprNG@P&*XVZwKWU z(4cu~Qf_MA;a$)b_9zYj`w}ty2QdWhQP8Xwrt(a1BPa(_10UW6YOsJt=8H>Gb3yCR z!21zkk(US>vor+TlA8~k`3LRFhn_W5tOFl#%mIyFf(IQzqsQRA>`CBtFS($l?_eV! znFbagP?v#&S)mj*L>rpkx0Zowp4Hz3}v?)ikm>j!uQSPk+^RTY7*#B0!W7grJ@7Pw1YcWdJL|4 z;Ik4GN|6d%P{STPA`32bAaMsCx&e)g!H$`Rhcvi@mze{qXh6+RXf*{oumzN9AqGQ| zK4{E4HMxYCHVmj7Kq{*tdjN~`b0EiJKu4A<>$yaa&E%^YA zF~H8mPzNoF0{5HrK2b|QuutKV_td=cnnrOUm++pGcR8u6g0O0 zt-SEb8ZjVbU5mlPV<4^IS#Z$ON_?`Q8CLjd7O)wI0_X;7Pym5;k0*mpR7x#M1dW*| zf~$p6hR{4ngA25v3AETEIVTZR<>#cPCn~ss%LDMDPlZZ24?YP2NmE7O*+)>D0<_Q= z+F5fgMq4)L3hCCuiV4S@l6)OF2W+B_0=P|)uTZK0+ALNA+a8E&J{PDnh`B5eE)1Vk z0i6z4k_jrO(Px{$M_TDYb(H2Qq+}*%WR`$uVjwBBG!M~{LJV5#alyg`)Jg?SeH9ge z3fsh-lGGw-8=^!#5q#Vj(r_4Pg$uMd4XW%Q^Tb8iid{XJ`LJ+-6s_>tA4t&(s?f^7 zeK1f5u^7Id1vD;z8pha4R*>$JBFwoXwCEwIH4)VG$S=}U2nBBmO|1lvDU~IH@9{3p zO)UbQO#>Q|fQ;&Ziy6qMC20H-bj$^0S|$ZH(!db!T3iC!z6YL`WpGZ+D}f$dfZVoc z2+NPp0kwgw7(mT`_$UUXTmu~kl?yt43ewmHl^KY0-x!cr8bjOqkh~5`@$QM>JPXaF z$UGy&1WpKODjsyZAIJ~jqhCrD^g$(Va(*6!%ivf98e&gXD1j)=2W@BsHItIS!xErI z5@@L%xR`?NSwocqw?iN$9dvv{p;7^KoL71xN{Iv)Oo5)<6`2TLl~fE~P=P#Vh_bE# zb)-ifdRhl)_f=|9NunNC6sUWqn*-kSkqK&AlqMB{Cz=x>jY2)pd2fl3(H2mD43?Z> zQ*NNbJhLocPazm|hhAb5sM_R8OD$3WDFn^hrRIU^CD3_ds2N2EI=fe#%2kkBl#*Hm zn!yJt1}&^hhcw3_p(7aPVh z_~k=3q=W9P%mJOfl>};NB$gI4#6vgsGQ@*U5MzjkO!gHq#5*VEC8vTed5i}KR}n+J z6KG*^5hx8O7eS`w;JV?{Zjd@BGqV&S1=9#w zWMff!Vi5yk)hcMsEau<}bQ@+$qCz}q30oq_rsUKD&>?s60jWjB`FV*}4DpC*|Kxno zotHWJpmk`FP*4Z00tIJHD~9;6ROljjD~9->RA{fPhymhaD~5RJxD03sEocD?DElD~ zG(pEt;!E;N7{I5P#DnW-PXB$ntXlqpy#gn>`;(@`i_uu=%m$SlsT)KREVuu_O91=XjO z3RVh{i6Aqp6s#1Y5)1Mf9HFHKXe(DyGVH*>#8d{*u2E3)1(emnhB727ARP>th-l9w zgHFJQEwCyqO)Sn-$V>+>1>Ibbn3uwkn3tK$0BweYmXbhP)5YLp z?XaILkyrp)FOr{@&yZNakd~9o;8+A&=*$2*whc5STv7x&EvhJy0X+3q!~k2P49X6v zMWB;O^FSx)f+n+a6Z1+GAiO}(`BjOfP+n@D0(2A@Bn!H_F&};=p+cns((og6NCdRL z6THGRH?Y;%SO#!d51DzcPn!-*^ zNzGG8FHI~;NrW8*m6%hN2tGOwW<@bWybI*GF9yhP8SM0Cg%VKWPDx|{9atTfnO6z& zigT($a%xIuPEI02a$*hxc(V(rAOIZ~2H8lhfI4slIYFlqJar1|YZfy&XCjhEa#B8n zBRpQ5K`VAaNBDvdnS%sGDMLzXG1$GOpxf*~OQS)9e~?fuWk@b#aD*lsQ zG%+`^C^IjS0irB9H7B*Wgdr(4vzQ?%vlx^*LD8Ma03HlYDM|zyye1~jl;!T=f*D=A7XEly=f&d5*B2i?ie06Km>2dXSF zIWsXYpP@JvGCx(2n3q|V&ybv0l$%<7cr61+7OFC}IJvYa5iA1Q5&&XDA{!K0py?;D zbb3){F}Sr0k}pdwN`Z5d6AMc-VLBm4_kc!KAf|$DN(XIXLQ0RMft^vpwli=;BlClngbPpn3t9h+Gh{3P(39-B|WuBL7gEdF{KDxXo1=wX`pqc zu+))~ssOr0zX6AsBR9a>Z z130o6Qi}@?uT9U-fio0R^FUfkp+=S@g8Z7ESPW`4Ddc2=;sBaj(sJ@MD?qnz7bWI^ zJP77wCg#D|$Vms`UYIP{H!u#^6EF_g`B1}Qu@2=z)PZ6hDgcRuWN-{YoC7fz7Ud|) z5|cq|E?`2SdnF6X=i&F9# zO7e3-7lpwBk^xq6fO^!hLIoDzX{EXOh@u0*f)*l>wMC#+MxcvvDl}6-DM?kMB)=pv zM>B;1E}a5e0}jggxuBg0dEgZz#qd>`49WQgm5}>ZQi_v{3K&3_rBx{;gHO|7D9(f* z#h06(mkRPmQE3%JdMRiwk0C8N19S^}Dfj}bqRiaPA_iDr5_-UCYB6{mqlBR#FDC^o zU6z@WSqd8OVMxhIXMi694!NxwytD)~0-2WrnwmvyvI5WLfoE25X#tHE2zY|p>kN?dcNkJjG8j@z zi}H&ZAl+95=*{uqK@?EC4%!X_O+OSR7J%247w3RFk)WCtRHPN<7FaWYoDJ$!>M=mZ6B#`6i!!V7 zK?gQ5WR&FQzycRENCa&{!?u>AZYqauCr4}~&rHr|$Sq3FWPohP0cF|T!~)RZ1av18 zLuPI|XmAxY?FL%43))iy+K&P4JEtVVM(R@%88Y+IGV?M^@)4lctN^+!B`2|{7^(p(%mB`05W66wP~f`(OHzwLow3T& zVk~AU6la3QK%p|=J4T>v$PEIJR0J_IH#ILG)J07N4LG1BMey1fq*4tudkP+;29Km; zE!nVWNl68jggNS=77k8yqw~k0tWCN zrJ}^j#8QUb)Vxy2L6o3YU_OYSU(A5Cjhg{6So4z_;-yu}4Hnwbi!_`wMm!@RW`KA7!P|yF#Tl59&j1_V zLESkA+B*cQr(nC~Q1;1z#+4yQRl?Wlpf3^!4Lm@PXam(N&{D7z)a(Tx?G6cP1swO} z1ePWil`#0GR_251lzaxrGU*&p6`Plw3Mzb|hw3vxY19l0$$dB)71(t^^BLB33)6v? z*om?QT@OBcic(98KpQW?!!uAzK|?G>iJ;Ov5wzPQAHhQMGN|PRPSLpYI4C874M5R` zzg&P`@tX#64>SRTniL9%g?c!H7t@Hx*O;Cyp)nZWQOw9!;03AyT?(l&tPtZD0@Nhh=1%y_? zIzuWZ2Jqp)p!@`C;3t+cgn(wwO2MWUF$AS1XMomFCzdi4rGlopic9jL?KH?t9k_;s zGNDx@lm~5hfh$QU8?}~1QwMPlqMn56L8&OATEIgxMWEvZKutz?RSA_v(Fm<9As5jq zfK}wf>T*y=98}|jMH3mI6TxVrj?jB$VCyV#Wn_eW3Mj&gKrOeTJccCD=p|@?6?E7D z_;w5i5HBBeBLgTblZsMOi*rCaz;q7AVe{6IwRhIA4X)OR@(p|*0c3kCXOF=rAJCYTW$XM26zjf})fnXnO}#{eY(AQb1Q@pzSOH&7P)Z7UiZAsWt_6 z>S9VF(K(d98~0i7ka2_K$!V?ur6tGeraBbW(v5*%t_5F$=8GRAfZ(i17y}5u_gv| z_8-cM7*JjV9RvlA%gizc@YXr_hAeQFJiIH9!3n&b3fhMSpI87o{6Dd{B(*5BI60po z3Dh=7DgtFl^0$=g z63{iVC7?a-MafXIn86=fAA=W_fR0uGFQH`!17Gq6rJ&wmaLs|7l2w_ zT#^X!Flhb|dZQTJ0z@5!U=>3H9~3!|vK0~wa6V{3PeE!C+#&^N!3$mu!w>>mkXy_E zx>q`%0d&7Q#MPiBlJJA!7{Wkn5MUmGHZj3t97zhGo5Yh8KsSgdDS&PcPf`Hg7@nj6 zx+y$K0dzxnl7boN7IOvAjo?WNpqs#x6f7Aattt5Jg=n1-(7rg(m~R!NafrkP9c2O6 zg!0J@eFw5y0A7d!`Dk_sByD@!b5fLy+tS;_#p6dZa< zFUTE8mxO1QGNdKu6z78i2{x0TR+^eu!cdR{8fHy}9#{=JnH(gVoDW*(1KtpwnVVXq z06Lf>A3O{O76Glb23;Wsz7Y;Q5CJI?jaqIiyB1 zx-|HB0mxEIh+m*htz4*&pcRquQGlPq>uA>u!i>|JnGk7pBClTyRP=0|X3XrE2 z;BgK*2M)YxCl@p!0H5ns0C#~)5{qHs2M#4rXAS9YC6KQ{XI?{t7{txV2NjNo*MbgN zhXfF$$Z&LGaC8EtSw|;b7iR{@h1B541epoVE}+|}(Z#?EEBLe72p{47(j-U>!Y-Ev-ENeb2yq2$PMx6uw8bB?9|_bP zLh5dV7kI->1M|Sgq8DX?vN}UjNiqZU*65Bd>~*@^e7D44_m0pxQAp zFC8>!jdWWysQhy*N@6I1+!hVKG!k|FDs1H{V$G^MXhr~XNH!=8l0jXUd{97_fUe+% z9)JK3v4ElyPz4KGeE^%S!vk*y1|9|mhKJq^415d>4DX=y zUvCBm0R{#J9v=n<5e5bZSs#dgBOi#kzYhb07y|=C0+e6w!@wZKz`)Sq12Jbdl)uV{ zfkA_Tfnl!?1A__!1H&^P1_lKN1_o|lh&ejG3=HfH3=Fou3=A9$3=FQm3=EtM3=Dq0 z5OX4+bUIXBnJ)ta7Xt%B9aLSXF9QQJ0|UcksQh$ah=1lo#n(W^H~2CzurV+&?11w3 zL+v~6%fO({z`$_9mw~~Ifq~(NF9QQF0|SG;AB48`gUEYB`Ne(=4AKk?42^ya46F~^{t!NoKLdje0|SG!KO`I? z{23So85kHc{UPR5`!g_@GB7Yq^oRK8I8^?MKP0@KLG``!hxqHiKO~;m0wCch9RM*; zH2`9sIh6K=$|nafFz7HaFysb6%$pSeao?f9mv3-%)r3#8*09M5G1^HgCOR320`pe34++0 z69n;hLlDG$Q-dJsa5hxmI;i}qAO;32kUxSL81xtz7^H$37<3sJ7(9a+7)%%#7|Meo z>3dBuBs@<-=?lRSe_juUgu~NdNIGT-fw)UE1j2U>fw(Ix1QK6GP=0*~Bwe?MK+@@i z5J-BO62ibB4hml=eI*1E9&bVz7&JloE))`PW}%Su;REHzhC=ieheG_{9SRAr`JoI9 zmJAFGheILp^EVU{E@EL2_i2YQFsL#xFa(4#fb(A&ls`QTl1}%ALE`;n7$n|rgh9gP zcNoMTgK$VZxj<=8DD4*x@o#WA#J+@ZNV+Qxhoq- zg+u)R7^R}r7a>M<^)7S)Tcy3%&(1vxO;viq}VK+B?jVt!5cSJrAm$&7fux&z zQ1SmzeR8po^kNzdiNAVAP$mVbmJiDz&;L=-#nmn zSRAB0ONoP|qr5msdMktSo1yx;q2^49gQUADTcP`@hCR+{=&v$$uOP z5O?S%K-}d4<))D0TS+O5+Lz-1S)?o0TRwn5+LOQOClsai6%n) zp_vFtr$&j8{Ns@b39s-(h`A|HehHLrOoZg~zC;EFP?O+rA|(C%NrZ%hQWB&-^GSk~ zTg6F``h0d01A{gL1H+LdNVt7SVqnk*wG)yd^_DM`Zcc`T!_H)gdk-c<{BtQ8;+{89 z{vRk`ECnL2mICpQSqday*r!1B2c>3LA`%~1Z46iB+hnF2{?-%}vr z&6x@bH-%J4IGLnE!p#{f9+?VJmzxT4PfIE!{Z4_3uZ7Y_p!#m7Leka8RERx)p)`LQ zgs%vtjng3Jxu!8NI599VghKf<(jeiqA`KE>8=(BXX^?O@3gw@J@~@>q;^}@GB%iXT zL(El4htvZm=@9w6bV&S7Nr$v=cBeBi7%(s}d`f3vFl1n0P|kqFXJ`f_KI<|d>Q-ey z%z2mrQ74@V$(O#Fka&pBgt#{+6B2$UnUHvDhVrLnLc(`xCM4hN%!H(qJDCg&whRmm zoLP|Yb2jae_97uRfh0=SV^y3^z`NowC2}kW*NIY2Q zLgLRO7h-=@E+n3_b0OhXo(oC$i*q6Q{&FrPf8NW5q`QAmS|$(TPpdpgdM ziy--2uL$BU=OReC8CwLgud)bY-?Acz|4u{s*NY(G{-+3HpHwjo=@3~@(xF$04&0|P@fRD63eB%SRohPdxERNb9oi2vRcL(+?I2_#*alt9V{_Yz2W zC6q8Qlz{qMC6Ijhvjmb4%dRB!5k{)C#ApTIRfP}MW1tdPwDVeC`_I=v^j)uk^dFwoK*V3vK+OLD<$te%`13zhJx47hTtsUj{!^`m=+}bs z^=cvUWLyhzM-)^(6-sB;GB7ZK`iD^U1+|d)FNMmdFNuY=eh2NlnN@^k7S?kIzb z*VIA6rvWP70X44=Dn1jcZXuLj3Kd@oPBo~!UOglom_p@U>Y?EPLK;_O{h3i1H?Yf28cZd4G?#jG(h6XsR7~+e<&T&0C7hoR6Y^P&uf6Br?Lh} z_|`+sYlZSVq3Zgf;?tqxv!V7aY=Fe``UXh3cmV3In^5`zRNr%`J6=Q0`vA4~2b9m) z2(h2D5#lfYMu@+}ptKZ}mV?qtP+ASDPYbHgpb_Fv^G1k!?4jx+8X@^PrV$b@8Bp=u zMu__hq2f(Y{q0bGenx*YW@wVzB^FhzX3J(G1Q(nO_1{IV-uu5z}^h$Kj=3zFc>i~Fr+j?>bvR9 zkoLjeW{A4y%@B9;w?OzJEf9a$v_Qh&p#>7ZK2Y&sC_fxZ$3f}T7Kk}HEf9Yewm{NH z4OCwfl-~wb-vc#&atow9n-7&=)B*{g6)li-u@y@1ZGrgjC{*8VsJiD+{+AX=I5V_D z+{@Vt(J#;nF;4=@S8au;(}nWQpnSVlh`-%iA@1>Rh4{k{Dj(Sj@m~_u{B)@PyjDnj zm9;|Z--cF5{k*spQVtw}iob-a=V^nOBhm&*$C7Q3c-Lx!m}AohakpC=B>eo^Anpo* z>WgTDq~}4$BQeE7T# z(hgy0ho}>6hlGb5l&{$ivCpU-;!ewUi2Lo^A?e1m9pcVVD4pC6$uEWNkn*_)YTkUP z`c+VR8&v)flz+7y;*N*y5O;lp+RNVo2}iLGi2c$XkZ@D%fVe{wN*hDf*+OZj4v72Q zq5NQ|z6hxLgbs+mvN|B~Sl9t^_oNO;yJ~F*q`iB(1LBY89gz6@1*Lg9A?}gugt$+o z6XGt-PKdpRPASLefiZCnQ|^p!6Ily$VY2=!B$~ zV^IC4p#1YtdoM%9Z$j<4*9j@FUP1N$?1a?!>|GH1#G$lC7sS7oU6At1rwh_Vdd-OAo~SLs0s94A@;TRLjBhZaqlK5eGW>$f|}3P2eDtY4`Qx%AH;skK8XFUeGvOYp!~!> zNO%?WLHyUz2XWVYsQ&eRkaA^jAH-c3q3Rz&_5XsJ$Jq}tU#uTupDL7Z2&EnRA@29@ zhuD+R4+*z=C_SYg;?I@+5clowhq(U)RNu9Jh&$i+L*j*f0>nL16CmQ+6Cmz(o&eDo zJOQFEaRMYfN+v+^Ro4VazMKeEHyz4f3Z++1faIHvQ1x3UK+3&66CmZuQKSX6a!c}W7q~6klid#bYZgU~&HgGPa z{hlxvGHx_&E+iZd&4rZrH|8=hI5IFWe47hNw-)mt?I+)PkoYKv(zWv-yY!^VnFLD8-JWgEz@qg8dA7w23@!`|40?+p^6QpotJ?NZ42PX1Cz`0QQ^36J+s z`u|dhKlztI#sO89LDEb1GRU~aLMZ>qGKl?B%OT;fyc`n$2FoGtwO$VKr`K}GxT*hg zh=014L*jAOa>zK~vE`6)sBg<5{_|M@@n7)@$hhkC6%h9yT>(k2uUA0K6JN=|5W~R0 z5VR5^zaC0oT?ujb@0AeuI<10?YqhR|jH~Tk1@Yg{Rgm<;w;Cd@xf(L>kh&V;j(Mvg z>HR2_KD`=}?=G%}q~{x}A?e~3lxA52Nw;!qApSR5197kO8c00kuYsiV1yK2`YaspQ zCu<<)@~(xX8xbgN2Bjm`Ley2Qg^Y(UhSIm7;)3fS@>Wnfc^xGDde%Ym!G?8^aK8_w z|F46jbNTfU^Mckx!mo2ZWSn>XdPun4S`RTtb^}D-aRbD>^bHX6rfq=a`)yG9#~UE& zn{y*Xz28QNe91HNY*NPKW@f|&0FrPDS+)OBrwn7Ga7C1_niXXhLkf?c0=;}iQSO!{IMI-9x&JgagWs=NVo*- zfrNkM9*F#sJ&+FY!Gai8O z{SH9NpXmo6=6yN9z>o=A2XGJ)Pn!-x%Hh2SA>-$_4no{5bqL}Qn?sQBjyVMJZ{8tD zIXv?aq`kND5XAkv4ne}_3Y7oq5G0&f4nyKc_b?>>QL>$)KWM4fF-W`x9D}6u_+yatopB5jZl%W{- zKMtusY>z|2aWa(NcN`L*FOM@Ygn{ba6A-%f1SCD)IRUBH1WrQY$L%DfUTixFNe`D! zLc&S%6eOICPeI%lath+#_*0N{*LVt&u9lvHgx|hXkaFtrDaibx)M*BW2@DJjC8rq} zLKqkrSkFMzMV*1vJN0K67~&Wh7}@y)3CEe|7#Jcz?bLISaQJ-=qF?PiB>y;^hxohrJR}~LL&d+Jhm?m}7a-;ZT!5s{ z%nOio*m(gGU$ZVi^6g3}{qO>${F1x~31`)d5Pew}A@+4$goMxDixBrcya@5>QzX3K6Dk5zb--5{f5#~ z*C76~yvD!~$iTpma}6?oyzd&M-TLPmBwg5Dhxj|;I>g^C*CFk*-s_O|-oopUaNY@} zFI|VEuh&p{o*NKUcpnTp3korjZ0mL7M4H7~L;mP?B;%`GJ?fMYXE{uE#anGcOkaTtUAtaq} zJc7(C8a{&fyZ#Xa!z2aaB{hUCk}$B^{5<}swcKK&RHA1|Ra=M#v# zHJ?Dzk;xNCx{Y`O@qZSSZg>I-hiOoH?GuRqk350+_v{l$y14@t*Leyt&-5vzUX6s( z$xk8Xhv6Bd-N5+_QXfP;gSfl=8N~jkXOR3f z@fjq4Eqn&if9@H?zK72s{`v6?GSA5O9Ad8V3rPIgynys)Jzqe~^@Y+AP&)Yq#Gbqt zkoc;70m)wzq4FzVK*kleynvXy{RPAw2cZ17FCgW}Hz@rVO0&F#h;zS$l%GN`A@0<9 z2{FeB%J+T=iI+quT@00Ph0=X585pK8FfdGi2}xHvuORs#98=?$cO*M;&e-$2SKmp2gir9#Ck-$25l1u8!64aELcZy@Ra z&>M)mETeks(is>S4BkTOtr>42_4S#zkaCOZ9i-fK zdIxcD%R7j^{&$e@obe74ew*Jx>^}gdk3-d+gUVlr>VNVMlAhi}`Tw9a=X;2`BJUyo zk$n$Qr~Mvcuhn}sdJpmcM5z2qsQxYQA@REx%0C39PeavRc@N2#_o4b< zzK6J<@dL#Dd{A2S1H?TtP+Ii^B>eS0K-}Z-0g~^$q4LomAmvQT2S|Qug37mjfVgKG zRNd?kkaB6s2Z+6gq2d>y{F_kzGpN4zQ2Gm0{3lc$(?^Iq_&-9zN$MlS{hA*k?lyqZ zmLDPc%L%G31}dKY5t7bIK0?BCD%89^A0g$^aj3cnA0grV@*~8*jGrL1;3tTF#ZQoQ z;PeU7pNahhNw?jfAmKIt6J-8sBUJsBPmp%>*G~|434VsSTl+I4{ER+B(qF)5NPEBS zGo(Lo>ocStRR6-j;LgCn5c36+E|+|P`1jctNd55s3nct)ze4PH{0fQh;IEMIiv0?4 zU&dF6KWe^0%E=z6{9>s5x~~v(4?)FGe}#m@HK_c%uaNSJ=^G?|CB8w-m;DA&rvc?V ze1q8I{S6Y%(cd8MYWfDTcM6oh`WwW&z26|=arqm>{#)N5>Etogybn#W^4hd)T z9}snwKOpvW|A2(!6ezvo2gILyp!_pGApUvq1LBTvPW@26Jn0+Pe{F{_7mbR z=bw;t5&aWVj+g#~_~#Z>{ZlCY4oZLj2?-yDUl5x27sQ=XzaaW_enHZ+`7ell0Z{Qs zC_e>C=l+7&U-k>)k3J|p?-wMUulof_=jVSx()p`j5dTa3hN##14N2!VzajGRzain< z`x~Nf{(*#RCX_Dt z12Lx@YEJ(j$T;MTKah6bDJcKjAISKC#$QM~A>uE@-fSpc0;OxAblYD@{^|bQhfw+rRQ~&aNW3vHFoO3r zu`@7&_tOY5FoO3JsWC7zfc7ofK>5y4ek21Uc>hQO10#4}O$C&m#J~vN$F+um5xk#j zHv=PhU(FFH{|W;mc)!Xm>~94FhShW1ywhh3F3}!``W@7qFHo9;nGw8SOoka^uNE`J9X8Am^L>~h?g)m;$1p?O zk;e>ie-ksrf4$5Q|IUJnZ-MID&kPB#6U>nG@PL^S++O_#mH!PDXJLWZBgF!-Uzr7B zt}#^H0V?jv0x>U=1>(L!7Dn*?tO}_3WEP0KRfb}@ zUo4E^{dlabjNtu%oU9OgWLP2QDzieuNskrcUI$i4I`CwL_%8!0UI$gz4%I)C72=-- zQ2Dj25O-{2g}C!5DthXH5au15TyJO0|UclMg|6ECI$v2CI$vW zMh1r0j0_Av85tOwL1S4=3=Gvw3=F=E3=GoDka}P(6QtaeWMp87V`N}h!UU<`9GDpx zDw!A~J_&dk6N$_SZ9)nH^`Sj5D@aF3CJ z!Ge*2VIBhm!+a(Nh74u~hGLMNObiSg7#SFH85kJOGcYi;GBYqtWMW`&Wn^Gbf%>Nl zO3wmW#K6FC2}-9jLdKe|GBGgh0_`;g#TO$3!x}~ghRF;J4Cags42g^k44;@77}W~2qjPigBT193=xbB3^$z)%Vr zhh&7*3sCJ0TcKv{U|?X-WQNv7%nS^#m>3wMm>3w+nHd=R85tPnKsES4{S*$h^BgEn zm>C!%m>~7%2dKJDFq)BpL4k>ZL5PuoVF3dJLmwjpLoFi%!(2uN1~DcEhV_gL4022i z3?fVn46~US7&@WuX=h|$$b#Ah+81lX%)s!Gk%7U5iGkrZBV^7SY6Zg^Mh1ooD90D% z4v;^X7#K`IdYBj(zCqo(7ZhgGX#LU2uz{J4d zk0f`DiGiU3G)@Xq$N*_mdxPQ$Nlgy}14ASe0|P5m3^Z?_$i%=fg^7Wo7b+G2wfh#- zZ6M>EnILU_8zu&ZnT!k!0igBIAPEKrhGfv5O(eDXj0_A_pmfQ^z`)B484Fy%$iQIF z#J~^^)ziYvz;K)qQlEo_Dxr4zFfuUof!5YDF)+LW?Y)J%=`)h~??DNNV$eDT5c3Ua-k*_y;V2UW!$KwohKr0046@9Sbq*7tdO_-zF)=V$Gcqvz z1#w`Qk%2*iiGjh2iGkrI)Gbzw3=C~BdC(X)BLf3JD33$K0VD+)3qA!^590HJ>}6tL zkY-|F=mMF=$iNWD$iR@p#K6#vC^lkZVBlk7V6bFnU|0gm^H9C(KbR~Z=?o-r~o>}FzM*uucTu#u60!JL_ap@ETsAsT8nXb+D9BLjmj zDE)%=k25kbG(hE`#xne4Vqmxi6|;c4!;6uD;W1PUq^=QauOSlygDohpGBGgRWMW`Q z0bvFPhE$Lu21uWx091xR)#pIPkAn7AF+tjtp!OAL4rC%|{sYMl&^nVgCI*HeM#vs1 z&^{B8b`M4dhH@rI{~E-Xhq`e-Bc$&D5}U=y!0;T&tfveN3>?f14CzoY(A?&9sGC6h z$3c2P>w-^$#%38A7|t>LPZDS^6e9ye4U~Tx zlr9(<7`B4u_!t-%YMB`r&M`4C9A#u+*v7!X@COt>AWJ~?3=;!`DI)^|3#j~qioqxs zs9!*9Q$XhrOaqM(LM7Rm85m}Q(h8`)U}9isVrF3QWoBSdWM*La5A_#FsWOzkmw|!d zAV>hTKZl8dVJag7LnG+y0FeI}85pvmaw<#=3W?*P#Vqg%1>OIE5z_6N$ zfk6ON9zexF&M0MKU@(H(^B&ZmU|?X#W`c~Vb3@JSVPs%92}=K*R4 z69Yp9DBm$LFw6nft;`GzVayB+h0F{L51{65VPaq?W@KP+XJlY#0a*$vCm9$RghBZO zs-_Yo#>BuN11iHnbt@AC!v`h?h8`vchU<(B3_;8c3>O#~7^Z{jU#R_BP`Zebf#E(Q z1H)pd**igLfti8f3=;!`D=5C07#Q-I7#M<~b_p{vFo=V~kdc952O|T+FQ`Ao7$IxQ z^q~A$W(I~;OptjFbtVST&^pux1_owE28Mm0x*OzgMh1q5P(3@D7#J2aLdK9miqC)u z1_p-X3=9l^86jhpAfYG_0mUqg3=A6?AoDKQ7#J9WL2XZF28PK{_kxto0Of6FNMD(Y z39@DiBn~<=14P3x=nM}K+mi{h--wHmfx(Fh(x?9eb)yLr1H)2~B2YUCGzY}Mzz_!w z%VUfT4D5^y4Beo%BqIaEBqj!iJVpivWl;PvFfg2ingP;o&cwhF!wi{M0r88O7#JQw z-TVkt_k+qLP#c7afkBy>f#Ee11H%iDLI%j(LOfJ$DKi5@JQD+h6eDDg7IYrSZw3a2 zc90(!85qJrWjPZALn)|T3DxrpEp77;Z2!Ff@TU z3=9m{7#SFBnHU(BF)%PhgZ4**+DA~ijZnSYpne7kpJHTS@PqR0nHd;1L)C!hs0*1G z7#x`)^TQyuMNA9~{R|8YAy74cnHU&uLG^MoGB7NKii6aGn2wAL4F4Gz7!sKo7?MEc z7Dx~z2|8~DBW1_mc)2Jo6s1E?O5lfHo3$e?pW zKpZ4|9F*S~85qQw85pjE+83=9hy85s1L z7#Ko8^)?e^K2(PRGN0JO#K5o)s;2;I*j-Tj4b+B#hK&Og149`z1H)XtO;DczR7Wr}Fx&(Qg7!Ou`YlWh4Bk*Xo3uyGcqu!g8FwL zHH-`l51{fOY6cSn!+p^FFVxHfP&%EFfuWt5fx(lJfnhZ$--7yOP`9*$&iP?rU1_o|s28JsP3=ChO;wu># z7>pSi7?y+D){G1cb)YrJAjMET8??usfq_8@8jl%JebYeo9wP%o1``8A4l@J8PN+CY z+iXxD9#nUMI1CI7PoZ)R%nS@Nj0_B2pmT*lX%!Tvj0_B?LHU+}fnf!xFAUXlhLM4R z5$Ye1&}AkD20yZ z!(j#n20o~JYM|x_g4&PF3=Hd`{7gm$hM5cu3@?}%7}h|=6qp$pS{NA^&O`Nr&PWOb z)dfg)L@+Zj%mekWm>C%ULDhlm24N;f28Iq$*~7%ZpaUv5pyq<)K$xG2fgu)Dhas5< z5(nWzP#>L%f#DAW1A`%`Ed^Rv4w3+s0n7{xnxM8Uln*+a2y`ydItB)YrJ(p^Vqkd7 z#K5qLiGe|wnStRq69a=6)Q&rh3=Hawka;N?W(I}|W(I~xW(J1$ObiU)85tNZGcYhb zfu6bb3&aMss~H#=Oqm%NGC^YkNPYmFtrfz|!0?#?vR?fj)IBiDikX2S6*L~fz`)?o z%)ns4#K7PTatAX5!!wXM3Mu&|FwCH;XOyOpotcxLR9TW*4B_UcrYAzVDGDG4gDQkB z1~HQJb4qjb5G=4@T4qkFLRx-lUJ6J8#4ASP<`?CHh4YJY!KyP-6H_wt(m`TSCRjML zBo(X7R1vTubS23AVg}V>g_P8^#L}D+g|hrikXwtP zh7~ImB<7{&fK(JG7p11=F=(XZmnP+;DkSG*CTD9hXp|IX79h9=3J_l#>M6LS7H5~_ z7cdy=`TM#mWF!_VWR(_|C?ut(<|(A+fdV{5 zkHImyq%<){A-JR{GcTRNF(pMIDL+3uH?b&NkHImeEHN)RRUs#{ELEW>H9a#wPoW?` zC$l6qFSWQ>p*XdqBr`8vkHIk~2js|jkSmM9JR}`pbqXc<3i)Yi430S^@jhTOh`}*0 zFTWIId~#||jzT;rC8ZW2M9VW$^AsxcON$iZlS)%kGE<8c5{pt5N-7J$4lO9i$xKcx z$;{7Va4bqp%1l;pFG@^FRWM|5EGbD$&d5#8D*-W!GLuS6QWg9Xb5j`{OH1-|6H79a z6LWGZ6^cs|i%JxV3sMuaGxO3F5)}#((^D0|)@GJ~0yZtPsJKKSJ|{mhB{hY?u`Dq& z2NY-uX_=`xDa8y zu7amRd1gt5LQ!gQL27adC~T5Ti;7b7N)!t6i!(uf(qnMSFDc2-RS3#V&nSU$^3xO` zxmS!B5fwE*VgHusvYJ3`lQ)NM7aj`;feo87LuALQ}U0pnVd>k2^ zKY>8Hsu6sR||eRt(M=sma+2!3C)~IiOf| z&Ph!yf*6-lnU|QGnGE%?0wi@5>oH(aQj}i~lV@L zfGx<+D@m;Y$1cbr`FSNppzM>Mrw|_kid!oN=aP)loQzT!t>BiKm!jYTDT$zR3IRo_ zX{n%qN-c(~LlOgLI*{=YqZHzO^HVa@GE<8byi+SRiZ$VufD&0U$PM{m??Zwyu_(1f z4{mH}acU7PqZKO@r9u)TNWLhC!MU`kIKN0C0GenRoGX)aps|sXnpB#ukds=Lnxl|d zqEJ+tr%;lao2tj)T$PFxzb>iCMX8CfC@d~W1xXfUmLzBBF<_M|N-RkQNr4MZ1{Y}I z8C;oHl95`RS(RD@7fUKFDap?Rc~P~P0aPX`Ft}tEr6!l;7lHCJM4G`RvltZa3h}9V zDGK>%pwc&0p|~P2e&JNlRWLD5hNUOBCYG8NieUh$>bvS4hl@Pf@U7 zaKV;46p}&N2b9yWOBbg?>H|=IQB8rH0pdck7p4J7axmSH5=cR{n86iVrMW5~RcWpY zkm}4;0a|~#hIlZzf@>QEXrZOxo1d3il3!%6px~NUl3JutsgPf!kY}ZUt}Z?oq7XwI zTDzf%<1{ZmF{dCSF|RZ?wJ0-LAu%sSp`bJmRPTY3ltOlDWiia8_%x6NsGdU+%}%XU zNKMYjhbzm45w#sES{Jgk6{tC)B!2O>1=|o#;FtJR)wTWh4|vsypq(s zN6hLKlaj`;badKh-sLD|Q=|xt-;98Lh zYQ><4xhWVLGPo%i8Zm&1e=woo4=sS)GV?NvGeE7*d~hpRLA6*9qyj|{Bm!zYfO0Z} zTTWtndTI)TTYgb;szPaTDyX1?lxGZXMc@_|TD6N!)QG_inl>5SQNv7!g%=YeWVSc^~r)>?qc78IqHW#*R_ z!`qA~DpHFTQu5356!P;@6+mq~kgilv^rV%bixp+2XJ81HZRreIfrCYqC&mjY>kqj)SQu_!%NAwMZAHMs;`M`m6shEQ<{ zxKDyb9771+yhoEMNGwWBFG?)PKoc)YOv%hwz#7uvjvShD)P5P7WEoN?4owPFAR&a{ zi48qHz$LJy34|oLJ%YtJENKI-2}}Aw$YG`txExwKfs12HD{x7?=>=UC7LQ=28@MLy zX$K*Vl75hcG13r<95y!~x{6q2v7{%sf!Na&TpBH1!NqZg=?gB6n#MpKnIzG8QkeR2DsDS1(u%^V~5^#}; zQw6wSL@x_KTHzkUCRvhS0IGXH>W~~=T7Xg<=cgo9f=ZL3)YNQf-C@Y!0qS2Oc$EdI zMc`2vPiPy^6S)oO32g&4SKd zB<5toYd1p%@6<|IFBq9!4Cc6k8gC#KNg#jZr7NVQg8PShu=WAC9a@qP={XeT>Vb77 zCl-{H7Nw?Gf$DgiDt%nTTzwQ&Qy6>_OUjU4!DkXaR#y zW^oB*oIy1OToGW36f^iBvMYSZD6<$mRD&c18b<)P*g>@!Xcz~lTpoiDq*bJ+pb(G) z>RBq3CuWxDG5E&k7nd;jCKhFbl5`Su^ujk0G*A+snpcupl&S#Air_&m2484bDXl0! z7pY&QTFl^^T9RnQ;G3D3nOmBxkdvC1UXlSy(zzg$Qd1N_y?ZML-^^lg$3Ha%Y$&Dx zsQUu#m8UR3yCcZMT*Z0}zWHUT3h}T843rDWDiBUdzCt{tAVBazqkUkFprn+VlLMA1 zRzPm5mgIvA4UAF-oTDM71;_;AG{JK_A&rm%Dz7&#?T~;5Z&Xtl{8CFYQj0*fdokM3qF-t`Bzu%3 zCV`T)U%mqJkO*kV7d)7*#{iMZ&&(?Ul`_R3KBxu&l`N%sDPVc9N{|G|CQ$nmG6MjX z0}sJK+Fiv60YrNXSrFXLLK1+tp;D0rVT~tbK~SqH6IlS!Ttd~4 z7pE4Lf&06#VP`!qP~3p0DT);mQAG1}OY<^8Va4E=UsRr&j;MqTFhmS7M2s**j2Zm$ zOF-o`ym8`}Uy`a&l95;fPPf6yMfo{7;5rCaQGt?LNxni-Drg+87&LnW9&Q2k4MF3M zU_X_BhQT1iBdWy={?L|#KXS{#AKG&8R|pOX^7nRS@P}p!e^^t(KQAY~5;Ulmm<>w$ zdFh~@cxE1`uUQJ3!ca)d%u8YLFG$UU3=zV{Y(X7)_()&?XdKQDK3c;NkeHcQ0vTH< zC;~G(d0@YT25!ny6(G|udJF-HPj8AXZ3(3w#^1}G0SDx3zMD-Fnu zFGN3$!ZWK9i&DU1 z#R?&bN#HTApwyDmB1pWa7UgEp{%}PrZUza6=geZzqy}jE4df`W$q;ih^FWya60(U&`K6E|3pC1BTvAjC zYAb>ah4hXf?PG8N5@!n1d;@q253V&oy$CcVnv__i0IH1wit_VH^O7^c&R__@Jt+{6 zF)M&iHHKn6hQLzLSSU197=lt0Q@{i`GIA12Qj1Fz@?cXB#h@}Bx}ZAPAw4fYH&rjcC>>-qNEyhPh&V(l$%>PUG7CyT z%0PJoY!Y%jW~WvrkMc}{(m*AOs#U-Gm2TFE{ z3dP__c9=dSwTRXy9`)d<_FzahO-U`zEJ{rQ&0RpeoRe6YUs?h(8k~(`^3WMQNMi!0 zY-MptYA(nND0;z74Ui~w3L!YP1io4VIZTmO1VEZ&khy-4ZIHYNoiQrO2akOx7AwH! zb`i5n;J5^pDd0&q@O&63c_t_3B!kC6K#`LQF%6^%(j z*gUR+1~?Uinp~Ord72EtsU@Wa3h=0g%_AU6Wzf)jW?pHk9z!sAKqELivp^v}DJL;6 z8{%Sy;QaX9REFS!M9_Qzydnq&)pHDBQXw8Z2$YV+SeloTTBMMhA75Gwv$`m?xHPAvSRn<{FpCGb z%pg85$}fj%FD@ubO-xZJ&PYv#4tZgQM@cDY!Za}lUXDTZ7Arsp4pQ=yOQAU$6uOYY z3sySeXhneCfmEXhe#NP>!{CTD=W z3!0dB$t*4ak8>2kMBO$M)-$t*@>5r`aa|6_zGzIGclM8PX`Kxxg2 zAsEC4l?l+Q4m2DG&%B^jPM~Qxe2VlyMwFBmGX#SMX@X0NN|Q@UixP7b&}MBxgI^%E zxaITo7=lX+Qi~XZ%TrU3+kL_1pp_G;#R^HOCFP)1R*;FhyhP9fEpSeRIX)S*$^*$} zJ%$hu{~$kxkRVrA1^9p>cu9%^Qa>dGG#lp#uay}>GEzZR04N`%f~o`1YOowoeyUVR z0yR)Ub**YKOc`wK6Vz7&F9It{&CM?Ztrq~9lb2c!HY>9jG~CG$k`Gx}mRJJq(kT>! zR`cnBB$D%UauN%QQ*}V)31}f0s036f$SH+%LBMKKpeswDNlGB+xrr6v5kQDsDrg8JBp(tE3dN;K z3c0Cyr7-6qn+|e5tR)Q53m%V#I3BDJ?0RULfcp^a{QM#XunLGjzzzk4pF&ASQGRK9 z2Dsr|4D}Icps)xs{R#0FLkPG9t&p1!s^&oRrtoQNs7!eVc$`O}JQdzd0d=zS6hLd> zuq`>k)CXGBl34+2i$NEkzzb|}YZcUJ1IDG5VOX;an|nxE4Fl0%3~DCf$eS>CLQ0w9%$(G`WKfxq zp9UHcNCmB0f*Aq}&60ctP=PTEX9%e*NCh{kQ!7gJ7($@~8llJo8llhujZoP5MW~*)o`P#$I!cETi=Yuh zs9rEOl^B9X458pc9+a=rL6vA?PI75ZVo81xY%qc$G!I-HFoYHqq!uM77N;_V79+Y+ z@koUsQegv95)Uh|oWTVanrvcDNoo8W~PcYre&Xq*F*yGrsEz-v14!6^~6QW&C)K!+7%2YRjp1qrlcTb7tpnyRPZ zUj$k~3W>FhR0UW&89Z18S{JGSQO6LLS`?oIT1ps}AD>g2n`*@no|=;k8qO}shxb8? zL5)N`EHWr!pi0R&t02TB>brFaK76q5T z3Jl>zi3Ok~upqxd7Kx$=h2$5Y@F6o4dMIKg`2~6mkO6j1Y7nD^X(FbxuNn&=YLTXwXcu_)JbY!JrEJM6wQWB_yO9ZXJ zECOXJP^nYQ5bv0i!w~NRo_Yh(kag1W(A8nipp}q`$sj$@g<=daDM&YlAs)J(Ivz4_ z1Ww5DpfPaJz;Pu*d_ZbZaekf^Lp*FnBxno_v_dkm1iIQ6w!#qHKY$kUpaP^UwFo*8 z#Sjk~WC0a?CHeWF26iz+d{AOZsue?gP-<~%2}3-zV+ii`#e-Xh3eKR`bP#B@AIPH& zP|-w?Z&6E(cu?#qBo=`xXNE)tD+TZxFCB#>1uKQ5qQtU%9ff2CD^LMml#`jNqmZIt z1)8cXNz_qDRj>lDLDNx4Q?OD<%daRY$}iDTNLR2@NYBqn(^1G!uu{m#FGL?T{SSb{irY5B(>nIc{SSb|c=ceZC zC=@GLDHLa>78NDxD3mBzDU>AUrRVD?lqy&$KnJFE6v`B=6v{F|t3P!V$`z~>$}=*H zvr{W|6e<*~6e@}mD|Hkq6|5906Z5iDQ*{)o6s#1gN^?pX5)~4YOG{E25*3m&i;_!o z({fTP7!nmg0_jDGWgr?f?8}g-P?DLG0^*kD<|LMuFo3lwBqk?=7J?_{hl_9a9fFZG{oFTD7~spT zK)DZAT|v4J3K^gwi{eDkv|1u)#W+GSXr*6KDw1wc;~cum8=@Jm7Sw7l%}D{*<4LIs z#ffD|`if!vqWtXCJWw};A*m#fA*nPcC$)qD)E!UB%*jb)NKVXQNKPy$1}*u@W&k&6 z8IqIo8In_>@~L?x#SDker{Bkx~Sr zzzxe35Gy|qM3&~}f#%keK||pTp#FGbQD$*|oxl*AxGd+(X1+)aOh#>_OMJb6T3@NFg8TVoa$T|Rql*}}6XQD&_w4;O} zC9{AbB@?ue7qoGPAtfiBAqBR+7c!2E+$t)`$ShWXG=e~j@<7AGiQqjMdJM3hDRg)> zH3i&rh80T%u!Y;0%0TnSkk#Foic0e!bs9m_kQ8DyFDEClh#@7vgaNv>1r|tgBAl|1PKE;^A(x3Yulk&x5!)Cn<*^CpEDQR272T#d-{&Mj4m@O*cRoNkyRT zTp$ThU6q`jS^^OV4TTlugG@*RZA=62l1j`=2aRDAB_fnT6B&5TCPZUyYDpr5RRAi? zAWU$749d&|n}VdH7~Jm$I{~zl3_O!#Twz3^~OmnI*XlIh92z1$hj)iOEIzc?_UlHbZV^ zN=i;DXh$MLZf0I-F+*-%DF`POfk=?1T+lA0V({PyLvASpc;FI3>Ox8~2GH&lQ0<+U zS`G?ZhP-^pY8+_)6*@%lA6K*V#D($hy&`c7K0=}>w-Xglk!SIEg1&TI0mQz zk&m3a@}apaAJo~*&rW5?hc+MbVc89|%qc&Q0kn2GEx)v=Bm>OMNX$uN$S+9EW5_Qk z$t%cXfDGN{Fo5@tfnp27f_Mv80S#6RSAwNz1}i{{TyU~PPf_TKaGF!VP>@)Z2qwUb zdBJ%;wFo3ok_p}l2Mg2!&=4+oUm2*M2x>SLq$ed7F%+biFo1@4zyzpNghX^fUJe7s z=)Y<)LqUE4C=C>VTDipxpojsrr$Hq?Y#;$ol?hS~ibqKGQ&67504u8)AO!(rW78Ni+TaoFh5Ei)MQ=FVs#88}E zkjGFAS>pj(WzSHYT$0C7oSF>U#lldWnwy!NpOX&~DJUu_Vt{S~g=APz_(GN|Bo>1z zBhb!N911`=42KjXQQV!c@(LkL#J%-|f%shtTf*eptLK^Lm zh9+nqDFbLI9~5*Ypw0-mVGUU!0Ism0Z9_u_WS$WU&lrW5$N;L{N_>~ELWTgF7Dx0gL_Lz3czcO z5whS_j7ZWYx;e;BDbX#;LCAtSeyK>(pd}-J5CS)a5xP=S zGQsU5B$3>t{NiFHejcP*2{!`XE=3Y4DM|#bG)@7n{Y^pATLF^5)R2~#Q;ZaBX^FX+ zIh6{aREf}=mYIX(_q6=H66mN5l9K$QRP2$MhLFLCB*G&Me;#@X$itnGsi39u zNJ>DpF{C0cE~!M$4+WVOsX4{aWu+ifkkS=Y4zhR@yIf{oF=*>)c~N2k!g_FRfyTuM z)1pk|^o5*>igHjws;C6X@5RZ9$gT%f4A@dNSR6A^7lZ3Jgv&s?hmm->phZET@dYHY zlA_d-NB}pj7Nl6k)aRN#L3Mr|{`H-b< zNJfAr<%;ql)AeY=#Tkhy$cYeSh%RJE7FDG#Xi^d+3oe0CIYr3nt275xMkHgFUJwb) za0XAzgAxqF!m`Ao%)~sTEDY)|f*bvbIiSH3xI4S1vFHxU}Ruuple{FYhb2eXkle)s%>Co zV8G>*SX`nTQk0li44xgbQsDA|7Qnh8sfoE(3Xp>|;G$LviA7w#p1!UK=NRf4aDm3@ zQ}ar6L9<_0;DuxQ1v!bCdDfs7Q&DkhiEU_zo2~^y9mvMC)FNHiyySe)Ar)2%7D<^U zToJmEeX1q-MOF&lPKimWISPh)hK713Tmd1_pMv#tLd`3V9&5jjbU_hcQCV&=5(| z(o(@*!9>AI!PJ^7LN_2ERMG3gf(ITl3^&_uHr?2MW2FKH19J4v&E}h3H(PFY+*omA z`OU5ytDvH-H@j}^y0IJ~nxb&C^=6yGjpa96V1hT6gOm>%iN!Z|-fX?G{>Dns!8!=X z(nt8l&Ks+5Y*e_h^JdG#_}6mZ)`+OxAYgj*$9qNP_|!%;+BDv*m<+%#&U34 zTLme4*4$Wsv*Tt9awZ>&YCxsvnj7nHEC+c8C9H1@fbiOz9kAT2aAO51$Q5pYGDq{x zt{afaUK}r0^@*CT3c7e{!gU0GgFdNh!S_>*;iWP2bxv~7lmK!S>G{6n0jSApY zvHoVqjWwEZu^X$wsb}@gE=>jlP$K|Vq8sWd+*k{$F+mM1Pz$R0#;O}DZgzo=+C!1J zvG!&wxGcCa9|Rd3A^O&X7_b6vCG_;Y8(VIyzu9#IEVur~@*B%;Y`g)IyRqtK3%LE` z2y5)Ey4iKJjp1e!xQ1D&aI+EA7F4*g^k$pF&E^}+Z?@f7r2vw<*?42aja4_>Z!8CK zw}9G<44^t*;l`?)jW>3JT8QA{7aT|(H(PFYff|%8H`d&2yV-HGl>yW$yxDeRD_9Z8 zUmzt6;J}@5vk?>^kYao#C3>j{=-t51z z5fm?=(As>n72?*dH`{JDGTc}m5AnAGxW(OaW9!Yv8*4#^ECM@fIoP!~)`JRbQ1St_ z<3Uk)V=*Wt-B=E``)2EnHK6DLHGjZ{-)z0H>ShPHN?*xvV+APq!65@ywDo4A9$4Fr z#h_pZB@u)qsAgCL@-spR;S*5!fvajr9D!4F(~X@_r{8S5vH8XdM0A4F0N6RO)S?Fp z;q^D$Zgzr&Z+6{m1t;Dci*Ibc*$9njPz(QN$Bp%RAct=Rbyz^bwh@%4Kv50x;|fqK z29#tOZnnnXY`L-S=ENIY8E$sm*amVAsODV-4w8-=n?T6{l)hW^7@QSuYzAd2P(}ua z0Kx~$Z??q4oC%R?ys;7FBX~I6Y`)nB&XW+&-#`i$P|=7_`HCCMZ>+nq>c&=ZO|$&Q zDg{vL*>$rEUJc#YbYmk(YzfE)Q04{oFu=vvT2OHYvbf`B6FAgvECrc$vkPPvL|`o_ zT5oniBNdvMK~oPmR)K0dh$Txwofa#w#j9_u0F?>gt{$jBSaY-M#xk%`pxg#&i7|j8 z=f>t6YZY#6ys_kF$BoTk1>igc?tp>0pmYYZ0#rEZ;nK48W+NyqV$pD8@r_+KTR<6T z>CI-4y|5$zcGZn#pezZBOHiaOzuBa4v;AfV*k8~VBG}0I8>?q%0(HP`S7bl*rIz6mGWMYyi6h z6!ER`ke=VoE>K{BMLU`f=d$alGL{KRJw+fblT5l}5vE{}_ zJ!rWMDm<5i3VWo?uW(}>I2kR27Q{DOK|Qq_>p&$bie-8X&Lu@Tpuz`{4{w4k0J#k0 z5>WjDuIfNty$)!eys-*Y1w#A+E(F10d}Gy(EnrWzfZTRt3#5PmIUCec2aOnj(j?en zkpAM$t{dxaHs08#aI@)V2dFdyMdMmf;=ZvOlu)3u;OcojC^}H&Z=lxPH`{LP02Mo6 zr@%@}kcOq;90IZtRKbIC0Vp4VmEAy*gQuLEt&q~30ikd`s5H2->}CtYjh#2PgHqr| zQ1!16f3xjoJE-`9Ie+tw?VwBwD(AN;pe33c>uzkk*$E2O9XH!SO-n?QL#+Wp&W2YU z;E+Jq08#;pc~Gqn!mIQcKrRHO0noq$r1}CyH>e^Kkj_0r8&P?2|I{f*V&Qv1e6a1VOf%@$Dg3`%EPZ>)rybz>EzbO6Qr@*Ci443}Au zk_eQLK&=eWagm_7LGUdgB`j>z%3LA-W`}|WB-Mix^jeT_VSW0QpenExR3$)S7CG~S zQWUsx1FA?sU73}73^z7{>Jy0CouCpPn!XT)l>)S)xY=?OT;YPoZ^2C=td?&DwQfMM zLeSz>pj^G`1|*$>t864cfJ^`x1-2CCF7SDkkVs%~1^E-&h5~V5EkIY)mfnr!H&%m! zsu9{|1C2f1Sbk&ejU5m#!>h&{^A&D@ijQ?STNEn61ta)0%Nwge1s0^e2QDI)-)y?E z0u-woL1i7X(eXFdgKA@}a-bN!LD(*M(=z^MD_S{uWATlRpw`sQR)w1#5Vx-d59Bn0 z;s@3s2Gy2eyI=*=c4QY~7z&Qr4>z;>|X2zhpbkc!Y;7hSnRXhLS_4jVEAgv>loqIdgqZ`bC6SW@XkfYprh_OaVfYyo z^EbP0Hi8;#SWN)6ec(Zc!zEZXBKs4=T0|QQyI%BK1k(Cmd}BSR*8zzgqz0W816ZO1 zR0MZ`E0vBLYe4zG^~QFvVn~j?u?CcSzydc`gGcaJflKNxuitWkE76;2t!zZv^h#fEsW+Z}#16xj7NkUIO(U)__VJ za4`uo9Xv=4YWlz%2e4WhY#^xngW7^eZ==K8@F4GiNAS^_{3seQTJaEDI&SO$CA%9d zLA5`~OVHLGq!-lz>X3JVV+zvx0ypn=f?N#Nj;#*{>sc5ORAER^1;}SNHr#9nmGIy$ z066qO*2CKXH^B`=P$D2oA=ocBR)LGQE>QMfPJ%Yj2>l9BC!gU4)HR@l0PC{cY`d`* zRuw?IgrG45P|pQoD;9;&VSiAg8NZ334h^Wc32t;jLIhM5gEQ0$Xzqe}3uG&ruR!ix zdb0`I4TbiGprL?fB%*Bzmq+$3sBCV8_y;b3vkPh+xJSP6#tKlk1#Bg#VGZe@5Tgau z_yE-{8^KlT<{KNKZ6AckkZo!K4^1GIL~!@qSPFFylEY!640znp0&37hr(&SpWT=s# z)Q0F!fZJK15em>W8Yr+4QM?m0+yokvz-P_P)*Cx-P6CA$nkr=HHiHLhK%JADEjOFN zV>26ZE58A5-lNNdDymLUmT3b`-hgF6O_m$Wz~fe+Jb(yUWV<1QM4+)PWHrz-8aeSn zx-+2A0mU|C{0hmS8!NH83pEl!BYqoUM!>@xB~c=hB&fHv{$>{}n?aR>;s7(oZ{SYw zAa8-oVDP*$XkdLM_F;8!n85-G6ad(g7HBl*1}qbTdS9Ua3W`pU1L27T)=)rE0Wupk zTp;~_NWBT}*{rzP1Tu#hk3tJ7lt8@Mf(S;qJaS|qR5_01jnZ>PCY3GgQp!ObU z)bwTtc>JUdtOx8NSo0IoxV+hpYuFn+QPgs?oxu|}kL3xfDPbcRo}g(p&=})-22W6T z0<=O2GFJsUclidW3EXlM-ZF-bK^ilFD-`ey2q?2Gz1amCLIk<-#wt(?dlP5?ALpANvxq)?9vE|0nn_V}ygZzoz!#Cg)4dCbpclSV}XKTSNZ7_HFja88GQBd{)7wI=U zK;v8t=zU74zO^^|Z)^aMA>lM!PvOSW8<5V~jisPI9LRx?KH91qi$Tk`!1E#C@g?w( z4n!U_k^!~^bT$f72M_E_umso>pqZ$f9XEDj8VK1Nl>c984ZA?}5*OMq|}-E7li zxUufWb}*p;%k!Yr0Lmd7L1W_E!Ltvb_C16LQVvoHPWKGRrS=NY*gewPts9^!0J1h` z7$}2{*nwjfTNMNv1qJo^ZZ?AY*P!{eCh(*kC`I9#P6baUHi0Kp!QCbBh#{!nhuMNL z1q&W^Xua72ila54(Jn|#g1X0`k=hneV!hb{N|-m6-&hEdTnd`1295NCy2v+M<8SP| zu>&&i44r^o0qXsOM&v25$!W z4Kl2Od-z+m7&KSX1uB<8ede1jH?~6)DR>H}>BiQZouDMz0-poF*$OI1ZmhW3ceBX~ zJSPqA6x?jR*?wcqjm4nwSqGl6Ty|qQL3xPv{h-N$n-f8U9w3KdK8#ELR%F`H%z}W({4hXa;Xf0?QXE|ti9u$Vqw$9>s$eb*0 z?U*vqsuYwJp*Dgd1XM&WM;fsLcmB3RCb^-Otw5cj2G`PHe}kd}R7-)XK$rt5HWO56 zthm`kx-+3;5@44h#vMR~4kQwYa~XP@WZjMJWOxs37bqh`M+zXO-dF~j2PV};p!@-v zC;=_n0DBJF4(cM$UEtAY%n=R};}7IPSY8G>5SA1mZA8)yLv|H31(4@G zd_TB-3M$9J?Pk!lK14I9!3b_;ZG!MYy-<)(Z?;0GKOxl~WQbxhc%&TEmOsZf3Q+SG6ah#>|L8`5t%NJY+Wp5c89bB+@)j1ukX8tx z>Vq_ZK%;h`l}}JPP)M~w2M>{=A9RW^WHuU<z$qrhBwgR*Q z1ymhE&4wz2*b5$4LvDDXDgrhB!Q*(Xm|g()WXKKFhc^g&=5So4azWJv)A8j(c^-q z#f}?mpprKhgO@fgzp+Y>ivct*32IHZ-dJ^GGiVJBsK9IkPoQ?)04?c(4#2{?bCB7D zn|M?}JA8OlKw3ul%mDY_x^8TSPJ2Lm&yX00%uz1})l{I&xdt>R0qyjF`URj22bzTk zH5Z{HGLR++sFw&@MhIG22p(lv1#0=+*aFT(8x=q+ar|LjP=8Rug>^yw5nWJ!NVmWr zQKpsvxuAD`6l?ptTQVnIO1h z0IKF;X#t)_7K7Vf@Qpa&as*cUg6zA2+Si6!_3#jaE?nO^t}XhmZOs2u_ug}MPHi6>#(^6P%9Nu9D)?Aj|cZ4 zS6YF(A}u#ofI4irMyo(x11IxUpgnJ(J_RgvUlM<>Kx_O~f$}hD7z?5fvX;5=#s&x%w800|3R;P95V!*04qlH43I;G2 zw8Rdyw&rHbjion0YtWX%@)`1SNN{De`Nk^HEIX_%1?mO0!#LozR*(V*G(`Yk`m`9- z^#nTzoIN4qE1<>V;1vj97vOdf(y~=>(gpSAL4^u@RupOO1QhkHH`~CyAlOn!&~O06 zZm3^CK>;Z>LHipm{e?y8=`$z?PrFjR!S4L4%*5g|MKuAt>3vmg%fjxB;;d+ysEEh=(<^ zAPxXEowtJe?~txNL=ZlZrpEwUtPTz&&~OH5bPSaGAgWf}0Ihh0HW{GSfGr2<0Tomb zW#Fi|*~I`_5(aLNK*AETiXVKx1XKXD6>F4r;J32iNKA@UA`tW7UV`E%f0gAaB8zD_Zkn#>#!rBRHvV$Uc9jF-tV!#~$YR!U% zYCtBVO;~IIg#f6eYq{AB8mMjO~ZFbh=gw^@N2aiGo5Yj3Ou z3xJb8xMG8r3!uUAwV)L&pptkeXwwF$Tm?07!JDRW>4S|5fQqt~8%X-Vu?cnn$SI&9 zP*8^kRN!t0l?=E87vZv9kc~%;pxPZ|2x!R&s4xdLFhN82Q2&BL1JZH^wPhju2T+$* zH-ox%(2^ZAx(O35cT7JG3F|z||ICVg4Wr&U7vZ)2s=>!#h@IAqx z76)__0;sRo2C5(+YuG`F57ZWdHsq1kIIjZ-Mi*%40kn;(5-AkTra2ec^C z1nn?c4PFSd3KT@kK@+B+k$BkD6TF3u+FAiOx|V}?Pp*VrECOy4YzH-yLFES`tiYCo zcEWGGu?y5hTLBuz-v-(U2HG108f5MQVtm*JqX?^aON1s&8M*O#v|jw1@_2QUY3GK-#OIa7SKV4+ff^5>%!Z}Ei4=hFat`Jw^o}Z`76KKh$Q}e)iD)E%Mv$Q8Xd`IpH7IuAhJ)Pz zDttg=EjQMHi#}*VkB5|}NCtz4=aKj;ZY(7bN08tG6_(&hA9$_Wdb16*>tZ8lqX;OI zwSv~Yf=dHXQx4RW2i5=3+7nbrZUoPxf{F`p>48`V3(f-INd<6)3%3xIx51q_()u}| zbOfywp}jS@iLgo&Tq%GnH&`|UZN&jQ0bDMCR`r9r8DRIoynu)fNcsR(px8WtX#(8- zE#S5kbX61Bjp!~!Q2}312iZ#r$|#_0wgbcf+X5+fQN`jxX%nQv3RGl(%3jbKUPyWZ zl{=tuQS@!2(8>c;0fE*rK$Ic+ZQwb?M#$cy)*DOWLCb9+_Cqy-tKK%y_y%;E8(OM@ zY(-HB8v6nz+*LQ*VdW2KUa<*OZ-U|tT&#i8F?1>f)Jt6kNzqhE2_W+pliuqE1q^sW z%VKat(h9V_as7?O809&zC|13Webiq95sqCsk_frA*fhXLe5(EbvbD$p3?@*A5#dA{YwX3$VEXyXku-NRQ= z8-fxGr2haaia-s2P>UDZodxeb1GPp$o%*hu&7i^)lqo@TO^}^asz%`3;@WO(1-ll#Qw^$$K^tPgxpx(KKp$Lm zfEFb$SGchPG?;jUm=zn?Ob5HB>&ANUb~DhL3{bxl*0~1{$$(pTIBaYTw6qztQxu#G79xzqq8=Pq z;61dU4SQe(kR~3eM{^St-&jls?;_g?TD1Y1b%FU2)w!T_3p#ITC8(*q_y%<2FKoC4 zw5c3LJ!D7()MtXI2lZJx6=120C@+Ar2xP|($Q#JB3ZO8@Ix>Rd1R_Hi8e+&pCm`p6 z3M@z)3}icK1Q|JA8bQlkz|H@gkdcy&H=98loj{or=a34h6a}@Bz-^z6pw$%M?jT4X zY^O6gCBy3>NJS2<;6ben&@=(4R|o2WZ2&c9TS3EGps?)%jSNGw{Zddv8`Q9X6q6V` z-@z-JAgd$Wz=L*(5gJgZ5^gqVcP)4;8Mt5rw@ko3fVMlJ?V+1p;0=eM<^Xt98|R`7 zu=_zC24xF~Ma#j*8h~0VpyCD8AqMTU12yD8>-!9r>m(P$Q7}}AB_zPO_ft&?a-F34?AGFZs#&*!gJCb0q!;Hh{Y4Yd`}A3Xn;x8_;bThm>byZGRbk~0r27d9QFt8=_ zRfAh2C>o$8+U`{UUIs1S(u0^%zns1(cb6OuNeQ@VsqBXtxTUrCQ*7Scd9Xl8gVv`+<& zQP7MwX!4~Altfp6_oai*;)9Mef!0K}!dh4xK{*EOTd*frfifbfuG@CAW6?vhc}nzHX=Ee7 zWfS*bxSxTyq1IDj~Bqh~1;0YgC6WCNxxr=5Vcu!}? z%@&4u==w*{B1}-UgF**1_yIbT1+<76WD%$m0Ucu$e`5>ic<}fjNI7gjB&d7` zFEv557eUgH_A*=&R8&AKK#&;tJOEIu2y}uDXzm79g02D$4uIBYgC=4a;z5%tpaFC% za9wm`y#mPo6`-ZW%b^1sAk*5c7;Y>@8gp8Tzg+?fbZCDZv>zH&kuZSHCxYcyq)H9i z&xQ1gK;8mZZliZ>5p~BFC_&v=4>}70HWjcEe94w0VqHffXkx4dG#<}@w6+61gM#MD zn?Y@F=r%x5HyPYU0hL6c9(WUYP-O+UD81PR8X~>f&Tz8>9MPbLB{=nf=4QaDh0y66 z;Ci|loTES^hYUBs9W>CySsQ4nE%;<7h8tUM_JM{&KwAeuS$Zd^OMGK9$Z4Po6I2L- zI!@q@Sqtbm15o9#{>Ea^4sqytV4&lSIzUTjZ!82AgrKb31}aB3gQn*|BG6SRphB?Y z#(D;DXK>?}wSD0F6;xe-R(gRsH}Gh^ z37Sp?&oF~l{DM~dgJx7gl?=Eg2=2qI0Uc;@VulwIdnx2D4amY zYC-0=Z?=Ob=fRzAumezC1DdY_Ehhp?-B=1fO99;dChP)8|E>viOd@m*7HHlJ+-ZPL zO@T@ySek^*=wb5&@yfx&il7>-12nV(YW=r?=Bz*`&VbH_0xyIC9q|i3F{$gujvFf( zl0os`1uES@>2~9dO*h*>>*e8XD2UI&x}k$F3^%rd230}Jh9QXoym1qh9NKQI0;Nwx zIDuZZd%Lj~v|JE64hWe70kyX` zgVrX2a^o6E!yA5(AF_`jO%0GLSiHg;P@q213eX7Cb_JMgK$&ncD9E4<8*t?du6sd~ zCE#_`H(SBs0nWNxK;ezog2MBdTsD6Dguiq<&=83Y=v z*a-5*wwtXtCxQk!LBoIG;uw_q5lIUiQ=oP|sQnB|SMSu<~ z0ZsUV8epJ^gO2RLnt3ka2 z(2|u7P*Ci=vF64K(0-Xl(6Igu(B?SMp*G+nAE7B2=0?zB5YQRopk11vCD`E51aUyI z&5`U6zqp_B$&!DmUXg*PB#uDN z0=26_X#})q7t{_1SEKO5%0S@(E|pOHv+4#o&Or4F=&(G{QSd8K6o6JIuDaO>i2@8| zkTqs)ptuK(C&1Syg5*Gh>yS}bP)T8x53LA4pY!v>qa2Guv9gOkCB6@pVa znwg*(TzGl}xd!Zh(3u2C2XunE?JGdr_du#)?Gxd$3EDFVZNq?a`;C?0 z3lP;oxm+C_n4mrdDEUFBRP>Oxw}P@XDaZ?FF88ZN=&eb$ZjOqzyPT10SzsHni-&xEO=YH3uPh3+M8WB zCxYAxZ!p3evv84}HID32TM|mBK_?ic3GSE`S}J02)~bO?jYHf1uH1$Z*>FoBcPzO9|H8*aYqh zF9&IWoKpZktg8_;L2Pp+s+*l1B_W+;J4enBd>+l;JL1T^%rjTN|8*z$@a~$ml_Ay8&8)xE~gwQey-n3Jw_1;T51*0Cnuar>BEYI0miK2Cqp1 z*+zO}1XOy1TmkDvqnw|F)))b)h4>Y`=Nxp-IA}-)5^bPj7nHgnJ!5c_3KWXqashE@ zG*aUTwUrMKY0#V?Xi5pP2NSHm4b;m7B?i=X2|Q>ZV^yHE2|GOmtPOO=Jfxuv8gu|H z2tYcl4WR;bz^Q5qw2%T7IN&Zfq#uJ=kqPZtZw76!Vkm}{pP=*5VaH5EiziS&tr02) zDIss{WB}g=3L2gVEyM$zO0XQ(AO`idZ#IF(Zb6mV=9{gc6bW6p2+lL$Dr!5ZG6SuA z*$7%{2tR5UQU9W!LJwNz-+E)o&1TTzZU)e(5NP5Tp%FCE0E$jfy$td*D0IP#nL(|1 z(8jgp&|W)MMPSpxz4jHLas**4D8_N>0G-(fy1f9@?E|G0P@Mrv*pG{&@dyYqTK{JaCC279;6v6ySCoJb`vZA2c%!>O6x+WLAM^1>A@2(;D`ZTs|4ykg6mlD$iYp}ydUUHMo{O-5F!rhwHhIq#t3F2 zf(dJNgF8x~VJ=X=9@Lls^`$`J3F)1)xnlAdiCNz~KPz zwu2HKvNG6C5$M7|(C{3R0pP3#HUP9N1=KnP`5sgRtOxb@cYz8ghzO{4kOaQLGzolh zDQHylX7i0rptJ)TMh6`maM4E z>1GQ^a@CE+;3dMK*nup70BHl&JD~nW2P|Mg8xlba1VM2DYUP5eU1+#~R(ODlL9ias zfZdJt;3Me4Nn|7F&}CTkLPoklUItCbwSX9)Qg*|Q<)9o4iq97C>StJA5o{u)XMJM} z*fvCo2}q;!UyA_mCypfEE*83?pwc{{W~07a=LbZsZ(w$3EbC7m}m zfi@C>_Y8x=1w8WyDjq>gm!atqBDMoofq{wvaBRT38(?|RkqRm)Zh|Ju zZnoao2HL(3nzU{N#Vlef7rbo;e54Gh@x2MOP9M6k8>P7gzVib#+62mm;3cD=+yok{ zhPSA}qBmB8W)_gzOgCG>ZUb#G0GG>9RUpf@GDN}}C@2TCmx4kTKJJ9EBmg0U6z-r4 zJrOGyKnt&Kc7Uetz*!6A6X>iqw1*BlA`K>TvlYBa6ESiPG6ytdy#o}Qpel76XhR=p uUIIQjh!6#x*KuR{ja{JNfX@knr9lzecw+;|a#*Xi0^wt{c~sCy90LFs9!enq literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ast/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ast/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..d874a58dfff82a5d2026fb16e2c5cef7a30c92c3 GIT binary patch literal 90157 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 G6Bqz=ZoS?B literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bn_IN/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bn_IN/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..dcd912143c2b2970b1c2489fc79daabba7c32db0 GIT binary patch literal 9285 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 T9FVs`=^b3WE?dC>>H-1)+ZpmH literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bs/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bs/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..2efb535d13ca9736c9dd44eea9e30a31ad56d469 GIT binary patch literal 108213 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ca/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ca/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..2b73c565e459e0a9f39c39234f1c4e8949277be9 GIT binary patch literal 135837 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

@DYfA*_E(H?`WtsUopqq1Y6N`!tZw3WJ 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 AcK`qY literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ca@valencia/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ca@valencia/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..4ff55bcb857cf229fd8887221f89cf87d23891f7 GIT binary patch literal 127374 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

xJm21S{o|B)Hn4=H| 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

iYWXy13|icv$)RS_KE| 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ckb/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ckb/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..71305e0d79a22266ad53363126d312d7154e8268 GIT binary patch literal 18871 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 I-qH0804R635dZ)H literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/cy/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/cy/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..05db475f35db85c54e119040742b55ea223f76d3 GIT binary patch literal 28432 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/de/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/de/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..55b625b58c6c452d5dcd4fe02122692bce686032 GIT binary patch literal 134305 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/el/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/el/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..bd726b580e28dc5534e47e1a0f32cb4f8a1de58e GIT binary patch literal 149866 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

%gOH$(X>keU zMmf+d19pj$dX1Xmoj`*pIndz? zP&7hEEfPUvFpwTuG5C@rNC65O;7HC^fN?-w9@S#-0F^>oQDSyUDYyj+8n99T4=pEy zs&6nC5{VElXd(k#6sIyI<(HRarZRxWvr`!$6)D0e5Vxf$fW~i%GLiiVlL0rm;G9fQ z36h@&O(AgM{1WgGQ4Y9_Ex|M%9Qeg>HK1z}5IoRI1h^EqKbc>U3JGYK1)xnW5DoBA zsQlz?>}dv(oZ!g_v3Snkfpnz<>w5b>IpPF0a{C%sE`XDaYYe?-0}swF9mdg zS^+*e(8O1M5yTQuMu3|Q&N1Nj6l%Ez>QkXA0%d2=$RVm|S!xkDp@EuCpb`$W+BQE; z0lQ%+xhFZlpeR43G`R#cxCJ_cJ3lW4G-inC2r(psM#&U%poKSRFcwuLzX;R?DoI56 z3p(tEh+|k62sESzP4}RZGbObc+!cb9prA9l5L`%frsSs34=32N`48b98e(wPP(8rXi_C;#e8O7CTKf5R556Ed=Y3M2Gp+uU7e7JA^}cCB^imR zqR`}BjG`2pP@#gL>5iOyu(nLl9gd*u&r0$^8Zyfgb3mKbK)m7-a1C4x>f@#s7lQ_W zK|7p4baE<)TUu0-0lwrN)USorTj{C!xv3>ZnaQB(U(n&Apo9q*M6JIugpsUIFG@xD z8kqxc55R&B*6{@g5V9-|)8Hi?DBB{!5XBDUavqBWE|c?%6mS^`I@<%gi^0`LN`47L zMru)RW(jDIcyfMTR%tqDy-99jNl|76Lq>isXq8AwW-@Y58lJN<4lg{?o0`p#nF3m9 zo}36yTJVMri~;g*BK9T|c;&4pOLP^P z2VDUQUX=>6EI$p@LxdL}49E&V{jpTgurm%NDA_I#)TPAe&A^O9P88Tp!=?f$UEnkb z5u`9Ba1rblVMt@K1yv2Q(-`vdi$FLR)YC0Z0ynThRX#NH79)f}X$6)qKsrh?6p*^% z;BGlY043`}#LH8QOQ5X}Bmp#qpyPWXEhvZsAbfbFfrm*@I<_VG5V1T3L^}W?f}>{$ z8fZcC0=R>W99sF{X;Va%22zhwT!RGQVF|VhGn{Y;qXl1y0&)ujWGgj-tfaG5=tEe=U0ZAzXvTe}C1q!e}LrG?04g>g_h_w8oY|!8Z zsO?=0XCRlPNWleb#Gv>LO%R)MaO(}S+zZt1fc1_Fit=Gi5d;%baKpxVQ&SKb8+OmR5UI`aWMm=Mu7}Vt5Trtcu%U?scZ~>9hNY&1NPw$4C=+}sZcZx1ZMxuH)S$(Hkct$n22BvO7@h&# zv4~8eT2FJ5Y0%X2f6^HSA%L7 zLODd1c-!(zQ47stgaAs)frx_(O;quM4A6n{prdd=!}ko(A|W}k0M0ChGhqb@ObW(F z$*xcnkmW$d2Rwzq7;@=?DTK`yBpo1WY!(&e=a;}74CyaJj0QCdkVdp% zg5YKgRDFs9xFrLVf{bo}rVn7n0GN$P+@StX31r+5sgy!gKyVhwt%v|AO@cNvz^M?` z50IgUVg^`G4oATWmqu_q804_^G z7k6iZ_Wgp)0(VQGcXLDPB`60ayMPNSq#+OR<>`=!2a^y7gF0SFTyQ*t7T|*mXBY!f zGK0qHA@k&r(h$st50b!mC^@UN0J{4Jb3~-HKmlCt!rcvTNSCD+RVskn!6+>%gfOD1 z06Co%9LV5+0WZ~pO{hXRkWp6HVvoYo#G+J&a!?051Kwe($S-230u9!I6M#ZeVmfrV zv^XQPfFUmxwEPdU*%-X=0z88VX5}W9WI!dr$yPN5yrTxYa4`dDcNdrdCEya!DyB^E zni)_$K(ZWc2RK7+UMUDC6@f_5_NL|Pr7egL&Z7S5g*c}1$ z4R+aLhP>2rPzQ%0FJB=EdeLBFaw>=mohh1_Gv5RzX2nlgiLXD?<5N=;79 zECVgQ1f3EJx=RnTH<|&uAssY7T+9I4?+03Rn~yxu*=U=fX`Ti#;#R0U^iuht^oig0?=v!5IZ9=CygP$AT_TT zGfH?I_wRY9}Npjoxl6b8`QPN2O<43Mp?kX9vxR7lJzfwDlW0H7^S z=+qdv+y@OEK?-tE>#Zn12dW%a!h+f=XbPcHP{)E7BZ3zjK#T#|gD@1b+yEj|oC!7z zSs!?q9o(>G2=sGgNK7g&0j=O+NK6Ku+Le=N@8l)t zl!9hj7?MFPMuy}f&}u3u1zN=hz8V$O=Sj^=$;&TE1r0uf=wgP{f=saeAO<9FgZ2-U zBr>E{B!cW>NCVAjfUf{c1r6?|f<2O+lV4m6I$H~Ll0XG$STG-SD zTcQ%^=LlLql2``rDL?}XNdz^-kR)J1ha?2P1~{_>Rf1Qv-15pZlGb3vMdqPdBgkiDa+c_j!@ z=r&65=3rP-0GGs|>H?t*G%SF`D@p~m3y}r#(So9&G$#j~6A_9)MG9ySGRzvt=4*sJ zVreKs4AM*i?}r61IV{#=K=ub{1v2b-Pq3@O^*yA{0(k&bCzOE3DnQO+$bfJP1GKq<;SdH;cLdyk0yFZ{AOfI{LX}BH&`l#p{S%F zkD;g>v|g`Rp*SP4sDPn3F*j8KK3yj-<7IjM-DIJqE?p*R_I_yAGBuoUn$q4%mg~bJ#c?`t`IiRR; z%*kQ!1)XaT+4hs4n+okZf+xs8gN~q>WdNO5nN$R7DMF9<04*5GO9!>P5dxqVpA%@w z3^)TYAehArPT)hOp;R&GI%x28VF>6RW2gKI1{fn1boFs&ayIBJ6b5J5MK{F^&fv49 zK`P-a&{d(Skd-B%^4vAA1avtg=vJ#-1vki*pdP7-psk+_P`Vh-0L_Df&qM@Wzu*bl zp1=Smiy1sYy?W44q8sR9Pc&{ZgHK{oY7T=>VqOY()g_Dpk^o&-134$Sm;r1y=oW-* zFaf&5pcr%&LUDv3nBwLuek&oju0al0$}Yl1gn@KC^027UjZ7H$edz^ zp!}Rv#F1+tqd|wYl%z6%4=#ZmPr?uy43o`#V9iM4+p{^K{@DJccCD zQD+R$b)rcnx;aG*NhP{PISimqQc)@cXrCZxu~$lJUNLAzPi9dn_%vDQrU&?51<>w< z{NiGU)V%Z}&`2_ToquXYNl~J1a(*7v1PC84otBtWoXU`vn46hX3EA?TmYI{okd~iU zqL7-FmYQ4ws^L;meG3}*f{MVr1!}M5l`v%HfktORG-!DqXjT(4^vwX;{|_H@V8{Wj z=15FW1Sc#ngl5n7)p{DN|HcHsw4@Nq(DcdD5Ruj6rj1r8%fc3c`nb0X(+_3Mhs$(8A)p5(fCNVPXzwi&HrybAY>VAObuj z!~hCL$gx1>p!;C+(jlCZ^c>Ls<&up2qCAF@jG|P~O8dm3640TU&@t7_+*Hs`;sOT9 zQP$weNARIbsVSf~aWN?4l;lG@{3S(+DXHMfyrc*;Seu#(ITQ%gGAIF0D3yYi89|n( zGC;>`!CQ@C9LPSSk|J=KQc=QC3f&7*iaaz{3LP3Ng^h$ELZvh>o1wG-9w=}IXjvtK z18oO`3NLu@ft!*=NNQj^R6v;xbU=h^F=T@Yj1Mkc%E}9hpxfv`2T>-cGL+|~FjVLk WXC#77*MR!866%Xen1d@*^B4esXtT%w literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/eo/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/eo/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..8f881345688049a68c4d4b5e11a2cbbd78bcd6e9 GIT binary patch literal 44083 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

P^a!Bo7LWFPaB=~6HVVLH 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/et/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/et/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..21ae14ccf07f9efd7b6ea95ec16653b5dac93aba GIT binary patch literal 19087 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 XhZ0ytS^#R>fjZM*22>VQiZcKJt6T=9 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/eu/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/eu/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..a9a8d9609fb7f5037d6abf7b4c2b6df547a2ddac GIT binary patch literal 132274 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 JfMz$_7yy$SFQ)(i literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fi/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fi/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..0c294a665f38e95531e00e4a927c199bf03e1cb1 GIT binary patch literal 101858 zcmca7#4?qEfq{XSje$Xifq|jLfPq1jgMr~q0!WmB!J(0XL5zWc!LgBnfro*CA)=9i zftP`SA+?c#fuDhap}3KO!Ht1|p}CQPp@M;d;S^N8a}xuD7Xt%BR1*V(1Oo%ZQYgKz ziGhKSfq~&Vlz!I4z#z`R!0@$+fk7GMj%EgiAO;2o!)68s0g!u|85ndJ7#OBDGcbrS zFfbfyhPdZ?GsL~`pz63=AmTDD5c`ZslBX6c`v7 zPPZ^Hm@_aiylH{BN2Qg4L5P8Y!KM|W-yh1)X@$7I9?I`)Wnj=?U|?9-%D|uk@;_Ak zeJjLVrZ$K>l-n2>*cliYOxhssvw`wM+ZY&_7#J90+ZY&_85kH6pyDZQknqldidRC# zYugwY*cccXTA}=&HUfkCeu;{WV!1_nU}28PORh4UgudLJbG*Fe>s?t}Q}O&`SE ze|?bfV(W*5k4QfxJ!|ws%yaCA=#TG*gj-!dB)m8GL+pLp5Ah${1O^5c1_lP136OF` zaRMaX3@1SR<1hh|uDvEe(oygPh`;kEK+?m+2@vykOn`*L%?S()`k;870CAtrM2Nes zCPMf=P&#TNB>iVhgt)tDA|za9PlWhy+eC=J_DzI@$EAr7`=3vQ#4qzCh(ARpLCi6N z@_i;j%84u}za1*S6w2Q}31ZLPNf7t{m;|w3elo;-i^-7m95NYF{*+9HnAZd4uY~ds zLe<@y4AK8@G9+BYr$F>uPGMlMU|?W~oB~Prlcqq@{r)MC_;@=7Vy@CuNV>F#(r!~B z;p96N5`WQCA?c=SD#U&Bq5R!bA>s63Dx`dR0p)+43W=}3Qz7LT+cZf0a!rH81OGHg zcqvYUgroH|NILMD2C***s;+Sw#Q&3_^lGTO!%%%Uq5M}+d4}nbaFCb|N&kk^A^wP& z4vD9%>5zQbF&*NLjng6Vdl;(k`gBMH)pr)ke+o7C*IY>aanFO8t2z&2uI)UCxbHkjxspB);=hi0ka(U4rME-r z3sCyyJc#{F^C9}h=R@3KI3H3jdCZ5%XU~V&*DxQFpJvR5_-_l8J^`ig%!kjG01c|4Aiy--oZ!yF?sl||T zPJJ;0gC+w5L&#!?y1K;>^ZOP<+%+94z7nc$=VD0w99zu5pvS<#@Dj?GSON)G>m`u< z7_bE5pHL_rzXamm%q0+il`Mgj3pGn1?p?S95>I=e{2NOk?)f5;#65bb}`d==E#N+#=knrYT264agGKl#W z%OLS?w+v!$^fE~N7A=FsXU8&#`=&30lv7KVLE2Z>mqFU&e9Iy2HKXMae?~2bwA1RB zL)^P`IV9ZAEQgf8-e)3%fiLdNc5c_LaLBg+h6(ro2tb*9T8OlGt3KFi@pyF?!>KRr; z)QPW#n4`TK5`WgKA?AfZ`Pr)>?rvEPv3L4vNIG8$h| zQ(OZv-(U?SoZX@PkTsC-&W4H?L-`GBAmP^mE7w5cf7=>J{M=as z3Ab-+Ao0V!7UB=(wGi{n) zX{>{!vxs$&bXLC(l8#ocgY?(#t%Il&TMzM<+j@xq{nkU=5ewxPtcSR_em%s!Gokdl z^^o?{;q{R6;OTmZ|2Q@FtNI0r*f}}(HO%Q#t zn;_+G!6r!hsoMm}XVand(M^za^BJm-bu*+~SBBC~P&#ol#N7>>85rys7#OB+hNRDH zn;96aK>eG|5c^cOK>Tg71>SY=MN&5-9)F7KpoFZGqVTYYQZvdA35-Np6L> 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%0D;t)L5mPCHIT7tAk81*IM| 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fr/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/fr/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..4acce04d0dc7f2561c6df407a90879fea6dfd47e GIT binary patch literal 136100 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

?pa`@q0dzDuL=cfkA$&;cf}~VP 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ga/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ga/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..48eb0dd35f06401435348f5c1674eaf11e818ede GIT binary patch literal 3178 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%0Aj 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 wgKyGLgA@Y;Lz*fB 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%0Di8Ge5YWcsL}y5o3T1Xy-(LH8y~&9#BO#`N68y z;Gr6jVW12SaXqXlySfp4fCSh&Q2N3%WD7l70%rauaGnOW9l+;IfQ7+r7x2yoSh&Ft zoB&7DKJYX&s7;F=;gGq_<&dqI>p-4e1=>jpsp7yxjbIDF#R+&y9_E2n8$d^mp-Ezf k5z6ru;9?JTtP<@c3$SY;X#>>2MHwuEl&q+OZJ=W=0Ch)csQ>@~ literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/he/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/he/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..f481317e1e71341a449f06ebd15e6e5dd4742fe2 GIT binary patch literal 97299 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

  • -f}REjNCLZTZI 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 smRm&=3mT`;`z6Rl?j}nVQD{0B~%#dH?_b literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/hu/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/hu/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..9ed8ad43fbb1bb29f6b4d74629a389e7702b638b GIT binary patch literal 137407 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/id/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/id/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..8c6be6b6ddbf9a837c4cc9662486aa71805f07bd GIT binary patch literal 127543 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 YD1Z*ZF3nb`V5o$8uoC8%%G5jt0C)A)OaK4? literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/is/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/is/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..8dcb1e827100f5e3c82c1fa2b297f58d890567d0 GIT binary patch literal 6554 zcmca7#4?qEfq|iifq_AWfq|ihg@Iu|0|Uby4v;7V!wqf*1_=fRhMU|B3|tHh44=3e z7&sXi82)lIFfcPPFtGD5Fz_-kFmUrQFo-fRFi7$+FmN+4FzE9zFt9T)Fj(_2Ft9N& zFgQcyy?7WH_!$@&5_lLGSQr=>3ZU|(JPZsVD{G+gtx$8P@<8lc3>9As)wdTaeh5mR z;eojC8r0s0JPZu13=9k}c^DYP85kJeL(OOBWnd6tU|Jq3W(e&AG=5 zapxOeh`+u=&1K|cU=U_tU=W7V>UHRm%QB>a9r`E2|Ue{l0d+%3!x@uxVHFUJpYuM$*T9jaarN}ECD z?f4e&A^zOX4+)38 zQ2P$>L&Ea})IHas`tR{W;^8Gf1A_o4UqIC}3qah@EdcSifB?jQasm+lstQ2#X$nB> zGZKLK!ve~87J$U7CscnZl%EVWH(vk}ekB5s_^A`zp!7K?eNTXaL6U)i;T@FEAqeregdil`)CD2_F%g8g+X+g02txelCkSy*D3p#D zgoIq&@$iQ%(k%6I25K_K`2}A757lznZCk#>7Eewgzeql)bE)$02 z(}Tj0e0)V1V*g8FNdEZ%6=xBFxKmODA}=ojafg}+M4i3}#6D*cNO%T`K*A{ssxMmv z5>AC85PKS-`lg9M+_ws9?sgGKxa|{x#N!R9y2m1rbnqRj?hlk^7KPZ$B?^f*Nl{3A zYeV_wq7ZXDMIr7A5rz08MigRRk|-ox(nTThku3^wccmz#{OyA3Umyzc?`lzqd$&N% zI|vm&DGCXfOHlqzsJcg@ka&C#b>~m0Jck&>oq}SJaFG>*l$*L@5O=wXLE_s>4B~EI zF^K;{#h~tms>_C&Qy>O$ca0dtf4yQ5_e_SWnbBtAn9X@1jIiJ zq2{cVfP~9>sQ50Zd50t*@p%R+enA3~KW<1s(#Kn)mp_-05#+))Mz|h9Pz+lS2z+lDzDL+AKS{N7@3PB78NF0FLX= zSb*9)ptcYL14A?eB%X~xiWnFeyr8rv0|SF9lnrVhg6d!pw+lo-aSW8MU|?X#WPs!! zTLuP(ItB)YW~iJ7sO<=4`$6eQ1_lN_1_lN#1_p*y1_lNjsJJo%Bn^Ptmmr}m1_p+B z5QBk%!JL7Cp@{)f#>Rr$Qw)&wrNF?z;LQLjvp`DY7#JAjK@0{4215o0hC~Ji273ku zh9m|C1`h@X1{DSdh9XdVkb!}rih+TlodJ^nL2V=hP&*l_7erZt2q@NMU|`5+U|=YP z@U@+2C@JTEH zvFz>b85~nm6q54uvvU)Rvh^68QghNXOLG-mN=uS66x@pvQ&JTS8JzM2ETlTwEX1KVupa6)WqUch19%~)FOpSh5RCgJUxbhqWtut)Z${N#3B~QoE%hs zK|xMtaw6Ct$m+r~^HTE58G=%aONug+OB71-tr&t6%TnRqEY@Q{4XWVO#G>R3h4`ez z%C9Lgeh<8rROHR#Ui1#YZEl?=QXNZS{HQ17P ze{Y6(WZ%StoS2`cP!0*D`0%2{0)@n){L;J>hQyqr5{5(&BQGNh`ImG%=@`A+;hoCowaZA-yOyu_U#KAtN=XfFUElD6=X*uOu;tA)_QW zhaoesEVZa4HAMleIv1QY6bkY)^GXm>g{7&*pd1~@Z2wFJT` zNGwXtW5`J@E@sG0%`0Wd&CDw;X2>mN$V)BH0p)_ce1)W<)WmFs;sTHfd8N5YsYML= zd8rC%`K3iA8DM5cVon-EL1Iy2dQoCQ2H5V@A_h=ONX;u@D99--1{0uE53!&C6d}b7 z1?4FWFc&ivmgbkFG8CnzXBL;F7Nw>zKtdHvLfwyGgFFD?L3~h@nU~H`oC?YI#i_ZO zkSHq7$S*2Mf|MsLpi+wg61Nb~6qh6xF@UmBUb;eFehJ7&c_|DfiAfBgbe&jIQpA!3 zE|(B|P*O-OLhy4lQ&MtL5&XP-g{;!zlFT$%)`gptmtT~dn1fIWc0Ga%DlAJfic(?W zTFg+AnUj*rP?DLOTFg+ApPmk~22@&tQ($RcN-C)AN@XZ5U;rhHOi)6FF%*&#ix?_X z^FRekR%&vIu4jsFSZYymW`3TP0#{IKL4Hw*u5WRAW{R#;X?n44NWPUqMoCG5mA-yb zX?j&=PEMj;dR~5Rs$PCkx<06YD2h)iP1j3K&$KTn%17|M3sk$MliMdt^p2?{>iFqlR$qF_lP;)Z#^K?s66LWPliyd+@ zi%W|2it|g0l2g<2i_%l|@={9>hFB?N7IXP}`nn>*%23aM%Q-)5ggTJTX{klJu6fD%DVcfcRtgqLnI&8SIi*F3Il6B7 zMY+XR3V8)!Zn3SAwE~1`o2Q^?t6*r&6`|{%nwMGx2?L+}?8KbRs#FC-JyR}lg`1vJ znx38sseHlg#3FFz>y%$~ctgqIZ8>F$pbFS6u?Wfm)xl1Omz5+clw}^?ppbNUb9Q2G zYEgD3q%uCdwm4fMBR?l6HLo~3QAeS;Br{#XkijqY@P^_Ng_6u1g|f^%P%eR0%nC_4 znRzKii8-kyr9}+E@g=1tCGc9hI6Ld`!kpA%uvAIn;SI&9C3%^7=?Y1yc`2DW#h{8h zFOk8msIs^uk-_oshV;~;!y6df5{nW+5smCPP;Gs9E!;sNsd?#{IXMi6drJ~?kX`C? zcx_%HgJ0(14W&g2rMU_@hu7wnGK3%;4l)=am~nVndQm1qEVQ5iq022NJ{44*A6{6J zsF0eOSDKfeS*(x|pPHGY0196Q*X-;}g|f_|>=K6H)RK}?1yBmjQb;|#ArVxgJLcq+ zFu3Ix6=jw%xPv2#AtVvp@_~fD6+>8NaY-UdBm_f)EU_q)!6!AdBvBzTt)#T*@WS|{ z#B7+z;SHdw8XS}i!KLxJB@7{nIf)>G!8J1-+^zu^H4Lt4Xt4%yX2#)_MPRprRiV_` z9)}kemn5boG6aL7E-gJZE%WdO23T;zW#QGbR~DpV_Bgz(1e&NA;yv;U3P3T)099X{ zcX%1dm4|y3;&T$yGa2HcUITf=HLW~ z#KRlP81mB@GKx|w(=u}z4(}=gW&g~)^u!`?3T8OGt%xBb>+nK`VzApG5p#H3T4{QT zLUA_8V?~+S3`vzmS&0lOiRpPD8)867+2OSXrFq$)^qLK>&@({V^HLIv ziVm+V0SOmpAKqKUke-#8laiZxctd7RamnF@*?HiaBby<;=OmQ`IPdT- zPR zL4H$6OU%nFE>TF$&dy{=IlM3@JEt-mR6ON@%S{H~%)=Y95)W@+0415MQU*}rm8X!A z0}?*GEe+(Evedk+QczGr9nX-OR$Rhxcwf=swM7ch&@2UcJ|&T%I5RJ=G?$_5@Y;%; sL;K81)!9)`S1ovTFN;LV=5FJUR#jJ0BREe0EJfkXaE2J literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/it/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/it/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..9e7a8be581a0186063e1ce03fcb3422a9f02fc83 GIT binary patch literal 132306 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�C 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�m|0o^+T9DAi3cxwfDG_}*ZqS! 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 k7 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ka/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ka/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..b69643e0195f96a706b5d5c5eea4307775f6db54 GIT binary patch literal 199929 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 umZF5&=P2P{+s~mgF=SC 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kk/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kk/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..27704d88f41e8b9725f13b10ed291b0abd0b6c90 GIT binary patch literal 14512 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 U8)7g8QemRyiXEUVcwqwr07R^2yZ`_I literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kn/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/kn/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..751dd45b2428f394933410d14dc3fe1c3103d95d GIT binary patch literal 17452 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ko/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ko/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..23ca9344e2b057e771c3db6eabf936cc5e86b892 GIT binary patch literal 34389 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 Sx?gSH`g+4gNN;$X literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/lt/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/lt/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..cb9b5b60f010bc3b1a1eaeda91ff47c7cf8766d2 GIT binary patch literal 135116 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%0D1Sl=Bz)Gj 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/lv/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/lv/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..a6e4e4390173d701aec2460d657cebfabb09faf2 GIT binary patch literal 128499 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Ųnx5cm9n(!7ok_scm#;?2+zk`BBbA@P>&2=Pz5 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 D{Heq03V_;y2F@d-*8OqN$ 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mk/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mk/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..57e3fb5fe2e00118ddd93f51f99153b3acb29a4d GIT binary patch literal 114061 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

    #n3Dst5v%~rN9-*? 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 Pf>ce=ItwO^wWACG*YhEl literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sr/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sr/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..467fc062c7284c6a4356ac2a36789e5975fd4764 GIT binary patch literal 161173 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�C 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sr@latin/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sr@latin/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..254bb9a33683ab07dcc3986ac0a653352cbb155d GIT binary patch literal 124739 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 U@k$&q2olF0?CZf(4&dwu065W0?*IS* literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/tg/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/tg/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..0661920ae57a476fafbbf293eec1b6d1d277b11f GIT binary patch literal 54363 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/th/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/th/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..4feb7bb6d662a95af30eacacc8c28a9f3d812a0e GIT binary patch literal 113790 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𕤰wfC2&`4Hv?p9g@93nFVq_ zBBYaz6n3CPaUhDoBxwB)DEC7ej__0t;evW-9DK(FlnY8|$owSGWj094 zVHF27H9?F7FHI~dEy~NxPKBBSQwQo5L4_cN2&A@ww-)k2{eO^QphNkPMd56S6`&b9 z*s2?_b?|C*&*A0JP(jvGmI+NAM>c||nnC^oWgu|)fI=UVtD&;kb5TyF0*We_8SqSq zDhqCkuY$RY2rtN~U58j651pcNx>=NwH6R&9X_SOzpXcy<8SrD&3{v<{9HxEy@y z3}hB~L_G%@HK|AEgEC5L5yaUUxtV#Xc?@ZZRXK?a8L34K;EY+skaBoiQ3`1KA9NoS zXrvCcwoFgW&rK~U0$oN~1a2rZAc;ThR${?J8941I?aQg&o1X8(xMIK@h^oBlg zR6rHM8&%M-M+snbHORvzQ1vL`1XT};9H=ykabS0X&Ts=SLW19;22u_wT0j{D$qZ0H z=Vq3GoS2iE2fh_GH?agf1D27Wn_mLDD+M|x0_s*mvm? zEh~cV<}3lt(B&uuGk^wU!8ZVcddINT2fB`IWg^4jZ8@Nj$;kzEf*~D32GBMNm^i5Y4{Di% zx>BIh9MmL(S23VEm;u~QRRA+VgaRUkf>UE|eoAT%=y(*+EH0>B13B6RQX%JOD}YBJ zk;4pp(L7ib#Ty{uoKo;9sJRRf4zzSf<{-C+P{iRicP2w#Vp2{bLm6bJTV@VJeokp_ zacLFk8VJxqqoC$yT8RRz%7#`dwjA$aSFIp%|4CG^ik{4zqNHrWttohf@VCaFG^d#jOP9N<>hA zyUP$RQj-+YTL4{{0WB9mfeP+Hq?E!A)daf+R7!#eGQfjxkdX`|ekEvx8Z<7LpUnUf zP690r0S|Z}@sX8*Y=T7}#9g5LhZ185VYL1~lE-0f4kV#O>>Xny6<{x+@qszb}GcyIb28OnakTili;GiWLh-2vxsSH&wSY=`{ zsKUfyI-+zyvH&zVRRle!DTe{9AKV~)yciGXrQ1KbQpyc~Gc<2iPkUD?xmO zGH~&QT6cqYfq^PmkP*<@8!QGX@DMUdpn4so2%3zDslY+X@z>BG6_6?#P*pcACB8PNFPd9@=O5o06Z>;wuC7z47GA|(~NfD(1=q&P9JShqN}C^HRI2_f;o z<34%V1rd!Rgl@Q4D(Wy3xEh2k-DW7x1f9j9kdl~_4w}G%*Zx z3DiS__pUHhklZ`MFacI{f%6)?C;^p#C^lnPMzZxN#-xL8NvK3B%aH|;OKGS$xHLx= z&jwu&3_8gHoa{jZG^q;NsRd9*VgYDn2(-Kck0lm^vn`@kjSxgC%fOi*T!tYOLI**S zRUwsJV8!q;1cWXHL?MPv5ZN?Px&<2p*McmIW*2zb1z0t_K?C+OXqzE;ttD)57NiDL zx`2ihp=@wN4W=4eLcvFMK?MaY_rL|=V=CF;%Jk^`)a=Zh6z~{0q$~s#g-G=%CKuT& zAdiBrP{_~8P0R(2UMnP}79}R77J*U^9>?^$U_9j0vw;U;^-gs{CvQ3^5GVV5edk?t?R6G0O%U=_us4B#W5AS7tc6m)+#Y;7ZWjE@0SCozDh zOCalGKrNBnyu*7KKm=sT516$rJ(VFlvj9@;fR|-4T85 zI?5bW(I{ZL5xj5+GPw*LzRm;fs>)LUjnw6of)=S%g2si9Y*c_w3quZ}1fA#&S`q=? z>YJqy>iA4-YHddvBhH*fozcTK}!+RG!e22W3d~__F|Zj3tA-yzUd?{5nO|$q%vgY zfEtSo#g%ErkU<#;37Mz{=l_Dd9EM87*?F+#6_8o+!^?9(B>+PvWdF88PG%9f#R^U? zh|M+yMWE$8$V;WbYcfiXY-9jm5dcf~kP;*Z#$_l<0htb7T2Yc(oSc~h+UAj3l$xCb zT3lF?S_E$8g9%V;0Kx!88MrG0F7@Gy5zvHTtA#+F3D80xxP!pDATTJn<3kd>MTUZkB}1llTB~i$z0X9{9p%P)@=k3q9x(i-F*Z338KJF~~I-v4uN@;qfxa znN{hB7iD0HFz{Su$&rn@SRxE$Svt1GoZz!|uxNlR^vB{aXmSSaErm8Q^RQ?~3N;33 z7(ts7phOR4=75fIKq}%6L!%m8fPj6;0QVEP986CIEgQ;B1TEr%9Q6Pyic*U*!TSv$ z4KGl085CJa4rBoJjX`%%gEnk~IbZ@jSd;_47z?yU8`Azntn5W;l))rZz&b(ArII4h z`e}yL;^L~*5{AS|(AhEIIES$_OHvuKD-SPEV#uxpX-F>0&&h!_MnSQW3vaI=dQq^w z9nb~S(6%l}b$Y4-c&!zvjSpQ?1wQu^G|gCyl5#Dqs#HfZw; zHVa{6(8$|iL1!R?))F&->PJxLA67>~hQpvu=j_UqqGX2RoW#l!1yzlL{Nl`#%=|pf z6mWPa=a=S{Xr@4xUsfiTB_5rx$B>;5Iz0%qM-z2VGI%No)@sp%v|vHKm&77a?f~!3 z19PhqLC4s^`LIp}&hvW^+voK_^W}Nq(c`2XP%9a-ou1)vJLp(?#M*Bs$bs_UArw$z zgO8Iiq!i^s`cO`YyX_djXKkXKi&s`!RLbB4y6g(vbpf@RPi!*Z>z$C~KM>ZT@uHX&2 z7ZA<@3A>hLW~Y{bjz7o)-I5JEQ9cuk2<%)5@L91Sy^zyfkWXF#o%jPegaza}@R>f4 zlYPJ^g%xKaaX`z8AzYAA$WaG2pCKTzC=t|QfHOcQ1|@>-z=pYI;w;w#y zpPCKd%LJDI_deh}@Zb@`9B?ZgRG7dD641yN#1{q(2(}>-+X#tmjKnrUVw)nd&5+pU zNNfuvwj~lf5s3}=Cc-J`{zS-tJ&NGwA(;d5H9`)<+tBhHvSv7&0erb1sI3h;jH(iJ z9w(@`ky8pee;9O+YBBg&a+rt?^!Q?hV$i4)XcG`<=T{#18WXT;`0x?9M#mxqzn1}< z36M@Rd~_qR2vXpcB;|m6oF$+Q^huyjTuuq-oVHR36Ep#v2V#Ts11N<_#6v`0#NY|*)|M1*8;)^t&E0lUxEyyA*3J`5jaPJSD%39 z^{c?!%D_vH87e`G!U{mGPS6sn#GDd_q!QhnA`n@W1Kt)4D(Dll!Cg~u3!DKoB?Vc& z2U%~6*g(esszQs7Y|IADJLDeTlZ~;%4BS}<9kyKzF$+8(3E74Qa!L+p=>bC`Xz2xL ztu#YQehz3>9NaWlD9J3y1mAXA4Bj}R0IumEK>=z_fw@TD1vMY@N zJHe1s#E?^@Tav_(Q&I#8JkTyYxILgl{Sb$3jQ$$$>1MNzH}~;DPR^1MQIokLD>rW3~j;tp?>= z#Ka${Ed{D?K)oyIu_L*l9lnq&opMvbMFvt3L;MXYEsg-j)M8uroImA^_TCabzQu4T)T^ z0~nyQ0N`W_O|tML4D}qS@dt?~&<41o)H2XXEUA?W@Wcf^su46|oedsCNCxE#Pus%acW=={X z188s)wEP{s`wUXFxg~iFrMO3( zOBqU`qt2zU5oV+?P0Gp3t;~Z>i9o^@M1nJ4I{4U|)JoV+%v{g{7|5+tAT1;0|UbvRR#ukHUKNYs4y@vc&9 z5O=T3fS7X}N?(Jjdz!((z{SA8@HT^ifs=uO;YS7o12Y2y15+l%9JWkIxbkH}#HFF) z@|g?_Yzzzx>QKI3Cd59oOa=yZ1_lQEOa=xs1_p-oOo+SYWkTX*J(S*?3Gw%7sQPD6 zalR}D1}z2#2AM1d25ANc2KOum237_JhGZz6nZ>|h#K6FipT)o+%D}*|D2stXje&t- zM-~G^4Fdzi{VWCsc?JfCm}~|H3kC*;nrsFJZUzR1t=SO&AB55uvKbg`K%fO(-z`$@h7oz`LE+kzs1rUEOD1fA&RRs(T$_xw)n+qV}dc6SRABIARf0YXv z7z`O07(5Cg?yo9@q{|K{zo!tAZe|ri+_$X|;{J<;5O>@xgv8I=LP)qU6+zT<6hY!u zr3fN#S_E;w7gRnA%5Q_x%b?=Np!`Qg5ce__L-MtDF(e#3iXq{WRSb!b7ASu)l)o3M z?oKhpz5j|K{+BF)=(jClV6b9fV2CeaV9;Y=V3<|Hz@W>(z;LpJfx(17c~3=EnK3=BPGko2&v3=*Dap!~Z~^`FZi@xWaU@uz$_1A`?41A}up zBwf~)L&ASrIV9XxmqXlrw48xKm4SibRXHSG3RFP&h7}O`@CrzNt*Lqhh4GAZSYDjonR72e70Hyt*bX+yWoZMEv_K6c993%|;&wHV_zH&7*-*N<24c=^sQUFa5c5yeKLBT~8A{KG(!1**_Fsppe_sbl2R!uhN%!gX5P!7QL(H2C zl`A?f6MBP8E4G(l*-CWt{@&5&?84ORE98Dc(53&cGlEf9amwm`)7TOjJ~ zTOj5nwLtP+c?-m!HBh>(1>*h*EfD|CZh_?c#VrtjoM?gg>oJu7zXcK=QmqjC)LS9( zX4wiU_XAoX_J_4X@_Sk<#2x*uka*wJ3h~b=sQM?Zka&L83MtpP+92UC-3IZOej6lQ zEZQLE`?W#hIiwAe&kNfi?rCU)*xL)`&uxR0L#x^#>EwPJBt1*CL&Lir(!R-Phm^nl z?GX2FZ)af8W?*1=&<=?oo(={EeFg>w%MM8UB@;@|?|`(!u697eji(b5z9O9ve@J#h z{HfImahFRc#Qz~s@f@glTPMVy(>fvfc0N@9rcOw_9ftC6K>07B^gpP$a2G_KN*5&E zSaw0;CA44$Ans=GhU63RZismXP`-ON z#Jven@#1cXd0pL*^uC}Q;*K>?dLNX&0Hq&wL(KmI)z8uciAU)kNPKAYK*BWuDjosl zr}jX?D;LTygYxToAoW6f46(5>ewhTNxAsHad7~fVp8rsBjR}zS={*5rUd03k23t_SYyu>n zPELTB`(OejKYyD5$!F3N85klN7#OT4LikfBLiBH)2np8{6Cv)sI1%EXXA>de_I)BG z{jyJjq%-+R5Pi0jAmu~ABuF^qOoF7Bs!0qCNem1OlP5viRo|er%4A5o2$~ErCuK4u zewv{4LMVM;GQ_<5lOg%)?PN&1{?lXz1_uTP2E!?kc23b0h&!fDfrQh_DUft@VG2b5 zU8wl$DUkX`XeuOq8Bc}yKYA)eef3mGy6Kn-(YJ0YB);}ch4}yUREWQBL-}8z`dFqx z)C*37_)C5oB-{+4e5YxU{17q?l8zFlLCTY!X^?Vv&oqcTj!%Px$8#vnIvo;!%F`kF z)^a+ef95+K;{Jx|koa0L9g=Q0PKSi^BPcB}0}>u~Ga&t%)ESWSbHWUWzG*Wc?wt=6 z-#7!}&+RiH@q8RAet!nU{ZFCdA7?<)6X#4w{h&7!BJVj9;;+z|5OZ5+Li{&V;;&UMJrw-*? z%z^0lm;=cd@pB;VE|~*K_kD99_O6-(vG@8MNV@qm2NEvab0Ox7&xOcq&V|IY-&{z# z&Y25||H8SDd@yk?B%U_Rg}7(iTm}Yf1_p*>b0O|!ng@~RoCisF{PQ60m7NC(KfQSn zeU?z#a~{OL$a#?PD4z$(2lM7Z^38szIhW=^{PkcSB%S}72MK@S`3wvt3=9nB^C9_T z&3s7tbZI^$-F=f`nt%B8WdL7eT_W9m-#`2vW}OS_H|zhoJoP zQ2o~zLE`HHl>Q2(xfVmj7{8IB;9u| zgZOVgRQ;-D5cBpegZTgaGKjmbFJoZH1+{;cF)-|AU|{fD&cNWrz`($@0%D#olnz+| z$(PY9ApR&`0ZGrbD)zu&BY{zXVFJSk1t|1R9Tps$ahv624oY^ggJ4C!qG7TMhBwZ7BaG zRQ?-O|DV;6^vSpe65o1jAn{?p2GTx>S_5%!`5H)h(7p!Zu32j!{$IKV;_sDfAnw=z z72mZ6lK%EV=^IdUKS9;;u7!k)_*#fLvTLE?2o={{3$aHZDsBZ;=L8jZgYpBR@}W?E z>{^I>64yf9lL0laXe}f^RzSt4LB$uWh4^b3RD9=JNW2_g3(21+pyIFBLc;MY)O_Z3 z5OrMZAnxa12XVjfI*9$!>mc?kt%IaT9jH3%br65qL-}6oAo1Knm3M&heb+}^;NsR#PjL;SlOO0R>e-wL&VC)AvMQ2UNS`RAeLU5Dzs z3)S}oO22^8Z=m!CsC{3ceBKQZcMEQS*e|{T;!n8^5O=9SBgCH{HbUINxCs(20-GRwkxh_rQQicxUt<%*--b}yW)s9dcPJgQ36if9 zH$m*J-ULbKy-@Yjq4XlC{8}h~Kh*qFQ2Q=#g1G<2CP;hr-6lwXTx>I>{pP(H5-xR{ zA?>#%n<47XZHBn_+h#~T{d+Sc{|an@$SZGw_|JO_MBIN1#Ga%r5cL&XAnBoZ3nZLp zLe(#T@|QsA)lhoV7KnX2w?M*W-xf%^I|=2Vhw8rt6~717_XKLs>n)J-`a4wq*A_^4 zGHivUS6(PBx)l;1vRfhU)!7Phr_)x5dOs*XdMl)UPu~iO*Xpg1c0darR4oJNA zKrRNg;7*8nDmx+WG1v)lpX*LYc*O05 zn3ud0;+{IFc1Nc-sPZiv5x_CRQZJrH;L?SZJvgYqXp`5U10C8+u@P`=P!h<=m3 zkbYj!UIy@dY~fx=c+J@h=@;#Q^6%`0#On_zUw9vcufGpszt=v9d$aaI^mjwWm+ynP z`#6;U1gef@KP3OE?uXdpu^(by4wT=%A7akx{ZRc-`6v4!<;DN~kn&pc07RYr0f;%# z2O!~F52d@I^mHh_7)q~)(z~JbaVUKmO5caluMa@t<@*6hdgnL@X`jj-gp{AU2O;Ue z<{%_r1wrWqD4hqTYoK%&l%4^lmqF<*Q2G#*z5u1~9fYLYHwPi<>iLmAnDEh5TtyHKLjZclMg}kbsU1E)A>;OC5IsCeFao}-62T0Z9W9?*M6w^=MF*q zdk1RI8z}wv5X4=4havHyco>ontPextBlCV*Y0+&2|K$Px1)FTumt7`Uu4T-ca$FBarea?+7G3+K)i&pML}rf9sAw%s&j} zUpxYF|Fa_ycQYJ?*duckVy@0nh&ybd;sHk?;hAt0;*Rp85c4{ZLd>5IrPmyVq>F<` zA@%9?qmb}@aunj84^Z*{P;+^XLF|(`262z>F^IYD#~|(rh03Qw>9S)G``eE}{5$g) z#QmF~^f@T~>KMd6w&M`@h#rTSt9=~e9?RnpdDr6*cZNXuiN_(~S8yES-;U!Dcg%qZcu&@lukSW@lU}Ch`pUB zAmO?IN^d;@vF8-jygMf#{&@-2_x%LK-2x{e@uqPS;vVah5OJTA5Pzhcgy<`Qs%wJM zQ%^#|X~juMdA{!?B%d6Gsy_|o--OclPeStBQ>glvCn5Fthm(-{?I%>8`4q%H_EQk| zi=Kjnhx#dq`6j0z=2)GA)Hilec{eCO_!Pw4=u;4PrJRD8pAFSldJ58>s)VYmf$DFC znm-B3p8=(po`Qt`CMbU&)ST0&AmMW!YVUohdC#HpA5Jka>|tbJ_;Lyot{cxl>YYPp zAmRPw3?#n3L&bT{GB5-%Ffizyg@kMUS;)BX)U%L!=kQrbd_Ou18Q1v@RcCh&qCVst zq@Kt+2WhAGo`a0v9XJPZKhJqczeeIb#NGDiA?Er+`FZCd;a&&j_ne2=HwVh!dLA;4 zd-OcS{Xe1NJQpDL%Upn%YjgqPZl?>7dAEWKkolHn7a;Z1jSG-?{R&mjei5Qy{30Zu z=t617i;#E>y$Eqf+(n4~@{5poopKQpkF%llJSe>oN-u%Z%c1ltD82R~1A_+x1H*=k z3=A<03=BUnLfjj62~sY!T!PfE3ob#%H+NrxjE{c01c^V7%aHkztjiGbvzH<1Quzvm z*1W>Nkk7!tpnnBYugt%~z~IBcz;NUW1H%~x1_r^aka?VYR~Z;4F)%P#T!Vz?>1&Yq zxOWW_9)GVfFr+asFbH3VF--4KP z_Z9;~G6MsH?QMwug|{K|I;(F(-2LV@WIloE4y1o*bO#czF?S&4O2HjS_;=iajLTlU z1Bp-JyO4A(br&)|9eWpIUf*3vx?OS?lAcfBg@lXvJxIE$y9X%;Hr#{Qx8oipJRaSH zjMx0V2Z=Ye`;hTSkNXh+x88@w%YBGC!3U6f-|7J*9PJ-K^hG~_)HAgYAmKgz0Ruxc z0|Ud#2axo``VbNxNe>wq+(G00481S5qHB;&$l#XpAT$H$O)@Sewz^mOzwWM1LbW5|4n+7pO5iBBN$F#QR{e>b4w;!hbE z{23S+e4jEf1cTN=K85K2_!N?!be}=S_Y`8vbz!1d1 zz_8>M#9!Z`e52QpeBKJBJD_wolC3EzpYA?bALYlu7lzlQk3_6-9=1Oo#@4ou%d!ma2n19+T##al=?ynYLj*M0{vFXJ5pLpK8h!=-nSd6BsHkocSS9+G}f zy=Pzu1FiG>z`&3ST9^3&V$aDB3=CNe3=BFS85qJD7#OC1gp~L1KSI(4%O^-XT<#Mj zzc_tjU@&K5U?}7f3qI{0f<8+4hxzp^Sln;m=n{dM*A2>EBj-gP7O+ z4U(Rhe}nWhE_{RJr;pzt;i~i z_#QtX>N0;o(&_Rako0-%2gKa}KOo_1^%Igm3!wC(pOA37@)Hui9KRs)uD>AuFaHIJ zhvmN@>ERVrUi&vhJoYyvTo(L>q}$iO85o=y7#QUKK+3J8Kag^K`X7ipj{bqDWB3aR zH{-t$cUJy|n78RKME}>n5dD__7#N}$7#Q;YLE`h|KZtn>{~`YI`wz)iE&n0v5C4a_ z|HpsGJen2*BRC!9GcbbZJ2x>fg6G$sF))J5e{Dua@cP6GMn>>_*;+sHx07{T)*+E7{#N*h9H z6Ani3x@L0@M({f2U=E0V#T*cStmJ^0bCZJ+ybk;?2P1fWuqY=Zc-^@mXfPGMPtb!2r8iEl0 z-cUMQkdYw-v_3_U5nRqa5QMnbT!<08U!YP5;;th?kZ|G?hJ<&NFe7+gd66(g{)aFl zxEyp6VFb5pW-T1h0#}DGG7VJyAyRx^+e|NP4ysV+60`P7;HJ zSECptJl2UZg4eBI6@#Rk=VB0lh>J6V_Xn7ZGlJK1Cx}Dj>%<}Y*FnW^i!*}P6aN&4 zq(2P_i267QNP4J|U{UnI3ywNwUmUI69c8YB_ZzEB?*bgTau9Q zQ;>q>qa-PaxxG>lb*rQx`RtSwB%W?bF@o3mzJ}6*(h$Bml#Z2#z{pU?z`$@+ z0TK=_ijZ(fRD^^>qawuqiHeYTKLw>eJ9;%9{t zB;Ic-LGlTwG9-M$lo=UHLG2D@NVzAa!pN|Rfq}tI1yU~jRDqOlx~h!eenXNfq`Y0N z%E+*bfq{WT4PyRbHAsAZQG=8t^6HTErJ)WRe%=6e{-}T z`R0`t#9cz#j11MF^%~lY;C94xZANfC%BKTKS3x?E{92*I2;MhzNCy%Q7jz)?8;dR@ zcwLLTE+jmfbs^@T(S?Nn7hOgM&^j-EJ&5}Q^dR+Ao*pB3U(QlJNcbPqgZN)qA5xB+ z=|lVztq;jR<@yl$W%`hKKdH|M-na5XAL6es`jB+xWB`f(Nd^%9Dg#J5{bc~L*VGV_ zPI3$(^~MB4Mg~97{wYI9eZgqN2;T1#V#LT02U_Q11QFi{r3H;4={f~U?=yy!w-P3h z@>|XX63-?kka$cqfu!F&6G%SqgNk1;f%xyP38bF?X#z>tW~LDR`KFNcGsl#Xp`L+( z;kYRzT-?nd`f|)5Zc_nz1dqq+5?lJ^ieBD&=wSi?^clT%e030 zyTlq2Z&R!x>3KVperOFTpSW!x`N7c!Vs8eNo?rv9cZUtcUQt_!dC|6z{8DWT$-jNJ zkZ{{)3yI(Fwh;UE>>&QPgwhpuka*f|2T6x}?HIxPp>Eqj@?nHMq&!Twhos9adr11| zwugk@S}6Y{l>gcuVn4eBBSRo)U6lhQUvxS^)bDkGr2m^x`7aKT@N{#8v^%CaGBU_A zGBDh9gtS+_J3;bYq%$LUykM>~Bf|y;1_oXiMuy{{^-3;~eAMR32<~qmcVz^(Pqp13 z^==!KzUamXUOy`14k@pr+!?|Bl@0EY`q0J$;x0cANco!S0VyxqJRte~x(6g2{z7R6 zPY9nGO0#)F!kH6FJ3#4jD80@T;=iY!kaA1Q3u3Re7bJi9dO`e=?8OLPSGvTDkzpnS z0|UD^BSR7+1H(dZNIAmd3kerrUr7F2@5=}te_--s1g~Q&^J8Q<$H2hw+7D6=?eb>? z?<@T44{2u!1wi6iGXRnv+yfx#Fem_$eo6x%@!kQYrw2gXw=4jXuJ;5$!sA^4B%DM7 zA+%v2BwzalLexb=#d`xG`E?bPz8VM#H-;bx%^bwYu$F;=fh~xUVKO5F!)`S9v%jzjcN~>fM#$5dZBAhvbVV z;gE8eEdr8XR3jL{`$OF#Am+qJFoM@(bw)t^zb+C&Z-mlYp!9Yqy$ee3h0+HiA?fFE zB&1z^1tZ18KMhs?AO=$YKZ$|V z=Yp}2@REv!q#Ki1h<)x*ac?L;HI@;)4>l9ZFN}rQR|?fv6AN)~e=Njb3u7Va;0#pV zomhzf9>+rb!5#;R2iZ7Ah7<+{2BkPixV6VYNg~93bD`>1LFsjg5ch6^%I}4mcPbI${+m#HpF`d87OL+9l>P#x ze?aL!iI8vy6|SIt%fd;Jc7%8m#Q!!)5O+r=LCVd9B#3{?lOX=6PJ+a17gW4I36gIn zCqdl5C5aKdKlWe}#C=zjAoe|m>id=iDR+J+LBdfu8A6LeX-Oz8lMJy}J{e-4ax$dd zrvViYPllxP=wwK_+ySN6B}3eC1xi0mhS>Km8RAd26o~({Qy}V$QXu80eF`L;qoDGs zDG>kXq(I!!3{~Hr0*U7-Q1MwQkaBSzRNuZ7NO^lS1?q38`QK6?;Ubs{DIZi*A@;hb zLh^4?Dx`cVhl)>2g_ye$Dt|E*;@)Se5c5B$Lfk8u1~Eq_4bpBkPlM!xwlqlkf0_oV z&ppy1_2$fUNI&3BIwU?FGa%s;kO3)YGBOw$(m~^)84!Oz%z*ggX$Hi;9~lsLFlR#2 ztw1IuUs`5D)O%+_!q*>4hh;*-JvI|!ep4nSzfI1Bn71|)V*d`P{tKCq@Vx@ne=8H> z--nrybn+i6&XffSPtGiexNH`rJW|MlgquMYWc(%|3*!C>SrB(F&VsmOYZk=*V^I2H z7NnlI1LgmKn#-IGF`o@eb7n*Q$phsJKxyG@h4g zfU3`js;|k0^e1L!L*nyuHX}nU0|SFo4kZ2- zqRuTJ5}twiko=wm6)(t#m{$$u*F)*9d`S3A&4;A>Mfs5U*`5!nuTDY5FGJP8$cLnt z&ro}L3n1x1qyVDNr~u+l*8+&Y5(*&ss{|@OtpH-r#sWzGItCSgS^x_rfD z%1~OP2+}XpErPgb3RHY^5ybu-MUeb(vNQIt?$9fR zq!&{t?E)1KE``KfR4K%qu#UJh|@Q#r&Pv&tdnZ7YYQyW>#vZb8j?SPt>myK+dq&Qbw! zw{``@UhfKs`-3VV=I2yE%qg#cxTC8Al3%7*K>DwnkDtI#3A-pF5Qh_x*>`l2s6K<0^%ZPgFtD*KH{OEtF=chJ>?lH6$NvR72v;ts3H<>}rU8?NI(KsQk8SNI2cDhNSBk zP;*#oAn8=91`>YqHIV$MTmy+$%^FDgU{M2UCj{3(%&)A0)bBk|{^A-)ylkt1xZ_|A zB>wN#K+@aS8c2L9)I!3^p%$9%Ya#ARu7&6?sD;>H4W%1vA?|30s-IR1iNEe)_qysK{_d@Z z#KUB$dDEfvvU-TUTcPHjt%tb(3Y2~bHSZnNo}cxQ@aAuTjMM5jK>QKg0BHwyH9*|C zvjLKy4>Ul+?@9y2JWkp2nkR5Mu`6%8zJ&Ojga__hKiR$ z#T%e>epHxhLKNG0(0A z;{Sjah`O*Ah<#B|Iu=SNKApUEC>YLR9@z=Z-NO-SpfyDPNsQKqwAo==A z3#4551(g?Xh19Rwtq}XYS|ROKzgCDl%As^sDr)jP8l-; z!*fOkhH1K1H&Cg28Owe z4B$590u}~_jZk@KW(I~^P&-5z85qPF85l&E85k6xVvS6Y^$Vc0zvh6>4P%6?%kgJ~ ztS9hdVPKGBVqh>}W?)#x%)qb+s;_~WfuV?jfngog9(gGJ1ayWL0|UbxCI*H?Xt=zB z(hHdw7$!s2NkYv5xnBq>*2==bzyej9!30?+)xpRBo;L!iyUN7CaDst>;T3wAGB7ZxGBGe%Gcz#wvoJ9Du`n>qh3Wy#Re|jCV`O01&CI}XmYIQ}hlPP* z4>JR3=m5jsf#E)qoCh-l!%Qe&3>qGqObiScp<-C#8GC|g`J%FkQnXwYI#)_GN;UW_Q zgC`RMLm4Oxm>_GeK<7Z|fbt?U1E@Q~V8X-zo|^^fQ(O$_uC+&zK-*Re*$J zKwBQW z46~r(Aif?G1H(rUgMooz3e+!Km>3vLSr{1JLiy*R>II?pure_)tYU%eEl*-*VA#sc zz;GTa2Qq30s2pKtU|?rvVE6(OU|?VfhQ`}ls5(~A`4S8a43C)^7(AfngUesU{Fr+XuFw{c*bq^}Om63s=1ms3W1_mw`28L2528Mmi zko9q&K>3Y{fq{bwvQCzVg@M7HiGg7m69dBwMh1rS3=9m5p?-PB%)l_0iGd*&%KyyB zz%Yr00kky@{EEJz!*DaA#y-U}a%ocm-0$$iQF)T2BV5Pe6WR zWMF7wVPIIs0NEeDl97SoAV?hp1H(d4dV%^u1ytTJF)-|f@3wAurPqwO%9*7T`-)UoHVCZIKVCVtWe~b(abD;WfLH)@Js;5Ew@>v)d+F2MFY8V+9gjg6D zc7n=o(7ZM?1H%$V1_pH|28QcUJ^D-x45t|x!1FIkQ1c?7^eJWrhE~w}JWzN--2-w< z7z+bKF%rL>iGiVsiGe{G8ZNV#85sIO3PE#$ObiTPL1%8VFfjaNVqge`>T`ptoyo+& zAP=<sA0&R5k%6Iw zk%1wAiGkrhXwHv;fx!l9FDFO=0|UcEBz-JQ3=C@+7#KvMexAs}z@Q3cF9zi&76t|# zW(I};Mg|5Ss5r=&-HZ$j5sZ-anGvA21q%biT}B25W>A^V!oXn2%)pQjs%x1U7~GNc zrL!f5aGQ~VL5rDz;R7gM7#SE+pkZJPwL2PQ4+8^(11OI}%>$XA z1ywhLfq~%(GXujfsCpMh1_pgb28Ko!28Ml13=Gp*7#J9#a+Qn>33uqf$Dk|28MqO3=G#m z`4{9c2FO}YD3gH?>V7^@+nIrZp&T@x2`V2!;m^pxAO>n*Ff%aNFfuT#0_AIF1_m#v z9?%(?1yK83wE86oRDL1sT^U|`t7%)r3H!oZ-##K3Tb39{x@0IC^8z+lA80G^|FWno~r$-uyHi-CdRHUk5LG9zRyIY=KDsO=8*H;6xzg@K_S>JAV; znhCP*8FVHph~LM=z_1N!*L_9?@Z2uwyfKhmH`JU*3=9lKP&MUHv1Aqo22-fmQ)nE4 z=J)-W85o{|&h>=K!Jz|I7>w zk&F!B^&%j5C^0cG)H5?Mm@zRh2r)7+*fTRQ>}6zNn8E;A!BnOSxpHO}6%nS@~K2P0%%JBYKLfq@~Bk%7UD zk%7SyB+kUZkO>X1EM^7%q*x@Ez2T0k!cM85m5N7#Q-HA^SBz*8PLpvxkX+!Hk80VJWB%W?^8M z2a*JxNewDL7#JA%L1iAOK8J>HKB$ez%)oG*iGkq}s1MA{z_5*xf#EeX14AfOO%M|U z!+ItLhA<`uh8(CHLB{5R`q)r4$;^;FGazvg-T*QeR7XL>WjX@`!vd(@NG1k`_aOH` z-3(HH8p>YA!oXm|%)sEu!oV<_fq{XWiGd*n)P4k=4+H80g4TC2LiRUZV1n!$*#OlG zG6!_d+Z09yhV`JfBa-++sNKGd3=FC)3=DnD3=EY}w>^T&DKj%L^fNIqyoB-(FhbVT zJ2NqWmVhxZF)}cCvoJ6uurM$713sRHWDBJuw* zGcfQlLH6EUVSwx{0I4fvW?+~I^)rZniIIU}KO+OfHD(3|4rT@hZ>U|MwT2In)JZTh zFxY^`7@+Hpm+sIg7&sBGBBJ5 z)%l>j%fi603aVxe3j@Pf&>2jO3=DQG3=EGM7#KpB7#R8)85ks37#P?X85pEk7#O5k z7#J!*XSB00Ffg+)F!(YtFfc>?a{+2r783(_o%sY%ImF1o@SB-|ftQ7W;Uj1a2XwAE z17sh^BqqqdC<|r=hRuu&3_;8c3>l#H>7e*zU|?usW?;AkbvKBb0P2H4?EvvXI33Dg z1PvE$76yg`p#03lz`(@9z!1sIz%YrCf#E0<1H(y>1~jb8$iQ$5>VA-vHf#E9?1H)@j*~-Gezya#-vM?~rU}9k42DMQ^ z=@-;~1eJZD{yfy({mcvuOPLrLW-~D`oB)j}f%@g3`k#@3;W{YHp!S2#`3Iee|Cfn@ z;T$6a!xARQ9;JDVkUcVPEDQ`>%nS@oj0_CMEDQ{9Kn@1&g#opxLG24h28K*#28J(; z3=IE4XX1m-gNLfw32GNJL-r`ZU}cnJr!zoFt_%?u0-Wh@K~;VcXcK2SAm%nS@VP&Zs*Vqo~f z#J~^@${Q>U43n7|80wfH`!#E!YL0@&dRQ13vY8kdwt(8PP;;I#F)(a`x>uH&fq{*M zf#Deg1H)8MKLFI11C5a~GcYi+Ffh0>GBA`v-8GMifx(E0fng%lfm@*TN+t$|PmGYg zUDKHu7+gVqfttS=s^%AzJ^~fDXJlXyW@cdMg}T)RG#(0-vu0voI15tG#K6!3m4C|2 zz%T(6&ddx9oS^Y<1_tn+q)Jdbor!@#nvsElAF96#G=2%v&j8s+2inW`8fwmOMh1qZ zQ2&HL)$e6yU?^o|V9){ewV-m1pz#DyJW?(o0 z8mnYxV8{l|Pk`>907)<~FeI@sFzB-|Fq{UphoE90Yt=w=1E97dsJ#l>pAHfP$t$R) zC?x0Sl;-9!AehAr3Mu&|FwCG(T$)szT$EW*qM%v~;uWM8A^55q$@!&uC7LM;sv1S9 z1*wT8&KZeCn#Bsq8Hq)S$t9^p41|>wBdKvN$tcaqC{-xV$S*2ME-g_=%P&$;)krKT z$jMAjEXmBz(=1j<%P-AK(Ziz)qy&$)%)FG;3e6OS{4@nsjgtJ5#2n2O22~Ag!U~xs zsksWpsX3|1C8>B76(g(4POa1|R#4R_OUx-v)ht#h$gD`sVNlh;Dh~30QGO0cT~2CQ zYL0@c2ABprs??C`}bc(BoDD3VWCukZTxJQxrgSF^B=y zP7n`jA()$AlnbN5sxwj(Q!*izK$&1+P^5y?foQk@!c?#@f}5LKT%4Gms>cP=0_7A# zcm=6N$*FlIpp=x7pIn*?Vi%<*rhrruA*Y9=4$LktNK8%z34$45rrR67=7N@2tq+}-M*nJc z!QiL>5^xW43Xb6KNs4&XQOU+Tp&&#P)$V^knEGbrq zFVDzvAu%t$QbDy?0n>juImm{CjRch``DtkkjyWaq zK43D4!7)!EwWuh+NFhHtxwNP#HAPP$EHkxSp(G;}Dv^_)4lb8dQcDsubBgsC9P{$> zOF@oLPR+?thzDi0)FOl^*j<(Rr9}$yNu?<%nW@DJiAAXjC6xu>5X#Fh$w)1NmpKJR z`JjjZ$4m|=GgT@SmFDGT=0Pki$;bpby|_3tKTnS3P3>-H35EVI@NE%@^7K39^Vp3+Zf_qV7N~(e( zgCi``75ox&QyCmfOY(CQOEQxab8;#bic1oUN)(CC`{5a zi;7DW;&bv7Q&LkHoKn*>Az_oBrcjh$uE*e%nv0aD9A6)1l6>93{LqaCHc7uKB;LXFm`?#w8@~y;8c{D znUj+WqZOPo^FW1dFi3OV_ZMgfC! zVqRiOqJmpdY95lWv56Xi)aK=vKtmc<(pvA+@3)5tNMe7@R>lP_-CB7Z)Vv6(gE;Up=eqITvu?Z?M<3m8jvK51KenBSgTn(0mIGLnO?VMkllcE4h9BG+(DGIO*151T^ z4A9gBqZQmh%3L6|GE`0>peQvh6_id>i{a{!#K0vh$XC!pEjYOdls|$}6H`));2Pq6 z^HVa@GE<8byi+SRiZ!j^GMU8+AU_r5=j4D25Kz)hPAp0-fjds2v^cd0lwd*i2`IQB zMF~Q_EVT$!xGJcEVy>hphrzkDs5rk!Aplw~!1zJ=r6401oJ&g-z~vB_<&&A0%HUj? zoRbO(;FQ#)(sTuIgH{1lV3y`7lw{_n>cQ1Oiq5>$3Q*3&%vx9#W~Wvvq$X$NL(Ijh zq&O8^VHSgmeo)1XT@kFD%}-M(D9uYQDTQQeuygeooU1_P6|CHL@eE>cNi2y^1w~PA zVu=-lOKNgaYGN_er^N-SAms&_CCM3j*yV~6OHx5n;8rz*3$%3|T$xvrky@Ntm0AQB zODZiX$PJRE6To+@$;*kX%7dVx>Yb)You< z-29?ch5Q0gd0q??ELKQV$jK}QH(Qf(@{_X*OY_0q1DDKVkSQqgV0RSjVbcrFkDyWr z)V08(7hX!?kWbAkDaynlmzH0YtB{tNngi;QU@;q1wq)j|7lYCiIJOj2Q?NP`rVy)S zPGV7dszQEJR%&tyc0Yo8Ubtk6OCXI_>_%r6<1n%yu_!UUD6t>|ySYV)DVg~Skod>0 z0@C!yYAafU9;+IZ7Cn**P*H)@(N-ux6jY!hB`q_(vJ{8t zM6?Srn}vD|E)dlPMfqi!DXE|~Z;3)tets^f8IhcsmYJ*o?Taa7WEPj?LsJq&6S)0^ zq$MvARN}bgmng)WGk_@z5LK*T4r(u_C|EGKV5_QD!oD z00Fu5%ucN=hM5$f1}auTRWphxtN@2A%Z1fvD9Z8@%QDj;X%1ODF*zPopedk=!G&-- zo1m+4>I7FdNtFum#i^i9KyoU~;c$ua{Gt?e!Q_m@cu>nEwFq4Xq#CDXC_#o(6)XsG zDnJQRoT~Ej^K?O@4WPzCd`f0wa#1F@F9Hi(a8(2DS-9qb+2GQL0g}#=GeCm?;B;1! z3hM77_loo&ia-W~vQZwmIj^SxY5*03hNdb(R)89?8L5dy;7&Qr<9Z4TA^8gFsU=7i z6}0)Jju?P|jS&{>fQqW(Vg*AzeA?j3LDe^;y9RAdBNciuql~~tf%|qy7DI=4zzGtj z(hXv3YDH#=0>YaxSx}jpTAZ9%kP7lFG(_~14xOc34|)nkCj7J$YE@=J^1!#^l0Qi~N* z^2_r;qYw(9Q4^4^R8Xv^m7t3iWu|9f2$tk4fUQr=OU}qIg6f6|A{uq*65!Sxnjm~o z7DF7=&r8a$Ko^H~KGDQM&ACc6F+?*CO#)Ouf=Y%&P_6+FdZ%DlfhL-hn3n<>OLNZ$ zwY#CgfZUKn*O3Vt=s{HtO6Z_bUJRwhB^W~R;W#uIcry-79J&35CRLmY(o}*GU*IAY zO)Y9m4o$KQX&e_#3RJTogy4w~J)OWMu%#7*BwBibOJGSeNOBnI1|f%;cHnYo=?5;3 zEe*jX@unkmRan9WGd;mIVNX*CX_Rz@Bn<5qV6!X}Iej5%!IH+{vY;db?k-?45PMpK zYsHe@;Bshb4la%>-N6-LPkV4_)bt0c|B{f$C_w_Cjw`}5Adw`uRIjKK@DRZ!S(0A>ss%xAL-K8D0ZQ4QpORFWs>k47l$x3it-cHyJV2wY z2wrJkdSX##VxEEpc*-_8KewP1H0|mEmw*jlcvKdo7J<663~-hLVuaQc+V${6?s|Aa zyB?mfu7_u^KV-;7!C0XJiAv1QMDJQT-h(c(ogiQ%( z?j=4ouOzc5RRJ8ypt(l|U&u_dLRwLNF4E|PYB7UvYDuCIgKuVDW^QS&LQZO4dPxST zfXGcONd~p7L5{Fu@Xag+kA$bDfDOeI01YBQM}|`vpo0P^lYV*(zWJrasSr{jzbv%~ zI{F13nMs2ztnke*OI3)6HBT8JTu9jj;gsYn#6yZ~1Rpd{3sQ;Nr73}o?xF-KsL%tK znvkNLcunvUm5@eAZIY9k28!+cvQ(^Yg2o=mH3ZB9sYFbQ;dF0Cer_t#{Uh z3?4y;2_V|aNajJ?$Y^8bFfA}yge#F7zDUM^+72jOXhRoG4227C*dmF-8?;Db$PHN} zVR!=;NetY)L*k=0Sdk=<8>$dttYaIX2!z%c$dOx|S_GO1Q%EdJ%*;tl$^ota@yk~L zuX-s)6V1~t&C3J@J%e9_mS`4ZZQR-+v zq`?}Hp3JmLgSLQ3@FW%*;yxse&m=flMl; zrhscw2LFQ8JV^Bk9aw`*lES7G0zk_h{NTgB3<01SY*1+ct)~^B#(~;+AYn)$Pe>Jb z2t|(}Ah8(MJcSg(`MJ5Eawk6zW*n@LLMjCG7y?p@K#>a_odK_3QpnGPPyZst2)ONo zqycO%Xgx`CHjz3&eo9I#&P+yLsgYlh3YmF9G8&{1vH%Cv8pue6t?EEln~|TF3LeY_ zEi3^|bwUCj=1F9SBUKv#XxegeaBBmXq4`DN=7=5xDLNr_Za_v+Vlik!6})5+$^%cZ zgPI}?0h#e7$r)A*(Doaob)TqEmY9>7qL5dbo0M9lhbjq~`Osqs$j`|vMy!7c$S*1> zO)pI?PK9@!0*X>Wt!{pJF z5a_ZK9k6|+#iq_#|({mv1E(0x`1euVZ z2A!;C2q?wLTd!bA}P@9d@6X+STcASOtC!!%;aSF zl8~fS1;|PYP%jfM5A92W)>1&VfL)yq4hpBlB8AWbP)b7*OiC;Q&t(S`<%3l@B^I$b z=H!4(MDP*op;5%$ic$+pQ}dE56*P)dlR?WukWC2(FL^}P0JWS2GMyNo0+P!s%}dS% z5C5a`6kIZsK~rprMU@~4@T6=ac+DgzGQlHMpfzj?DUjux3aNQznML_|pb?W|g|f^< zg<|+JhZIo#0a`1On3tlTU!+i!npTuroB^t36`=)($By5bH}75{rxT zLGcQzEkKJPL8%>9)`5DLpvoLFR|zrzyo^#I5tONlQu9i35Nj|I4h5?LMK5fvYfvh9 z$!t<-I%F9oWCfEhXsL-qdLGEL`9U%BA~HA(BPOJOdut*C>5NAtzaT)`9&}`sFR#u1WsJw zwoztYaS3>CEsPZhyR{-;M zBO@atb$xwxU0ifMJgj_ut%8H~Kx1uKwSck@Xyq(u5nc+oXUGr?YM$gJr!oYmmcUoZ zBd1ZM<=l``q$FPf7TB2ZcYtu@U^1ugdl zmAs&86G4L+1t0^9K-1)~rH2X{;7kwd;(#{QfZSYKpa4%YuvvOUD*`mh3aT&l z7=pnAzrmRm3NHC2#SFpOnFR{*NjZsm+2A4eVus-S_}o;6;DSWZv@pEA6!^ZbcLD8eO~B{``INl2old6~(eCGFsCVW8n%P$@##gQ>|G zpa=mqm_REb!9&7DFp>CTSQ!XeewqSVB?<{#kQU^?2JthC6-x6EqZ%-CV6C(Gs#H*& z05PmQGbaZ;GMofnxRIjA1yT;)fs&dG-k<Oc`uG z4nCe*l$x7g1{!Vx*#g>c12QYK7~DAu$;?d!d)XziB$Xi~AF>52u_P5#1Q&xEOrU0< z9u}EmQ0EaWk({5ClUPuk3R`Ifo{m%~$SH*k(}2~aK-XtOjRlPrDI^vZ<(KP#9G?lD zuY}4%#%jRQ;Kg6*;59$F&?%V$aEA>v#1HB2f|65iVg-1*1|pXV+LIcR4=T(+>+4IC z6mnDZN@31JHXYiNk2HruN18)n z1IwX$-g*kIdFdzvc31?B7((@ev8lumG-3z^w=h7N0hEi96LXSFa}rDPi$Kj4&=v=V z&^&M<#t;gvl2wZtLJL4!b`y(J8A6Lw;oA}8k!k~^ViuyLC`a1|WC=JkfIFuk9w=)T zL7HiLV6#FY<6@wBbOlFH`2$h~ty)sS@dWB4!`3jkLe`5ymwCcW&;d`w>nM1DW*PH~ z6hNzSLF@e>L*=QU*#eNgV1u|o1C+%IXa+$=gF!_o$N`WI`w;6v1DVhq15QDDP{sLq zsR}8X>6zf&ZQ!Jp2uiak>+kirz@ChU)nCq_?MBE|5-6+^b4pT+K!cD9kX~qhQ6+d_ z5jtUy*b)U+3=SjE>TZxbA!BZkZ~&J^pwtE~CPA{`kpRdJQqUf0h%y2Lksv$Jiz$#< zkXe4v@N#LYo`Qc7Xp1U5WK&X$!5vrVs`tbks5+46i(riqP)h~egI8n-OD&2|0&Q#y zOD#$Q^$98&!t&#DN^?`K7{JR*A*2F0%LK#r?SN%KLM+hTK@e475%{_tBr#~y0HF<$ zio;WLl0k{3Bp;rbi&INV3-lN;Wx!%cZmLLe3c zNVFK7rWnGD5(_|kdO=|cSs$Q>B36=LpvMpiEfgYQ`9CthQ~@?R3!be44HzSjKIFmO z4=UxMd*`5=-4*f+QuFkxjioxG?NB8 zJRw~HxasYTF0Y3Rd9Vk2(rz3RVhf`4uHa z`6W6E=?Yc~>G?TnItm#IRtg#UC8;?&3YiL4pbmUyqK-nAf|Wv6X-;NpiH<_Hf))7q z5FLda1uKP|%-lpBgDp)BLmZm19ChI5^DOf2K<>#j6>nIc}SSb`|rWO??>L`>bSSgew=B4NBD3mH# zDL|*lbri}JtQ5*JlS}f8bQH=JtQ5*KGK;fQD|Hkq6s!~~iV`bz6e<<06e<(*vQtxa z6si=g6sk&dN*NLr5|c|yQW+8zk~52vOLNn5QY#n|6+i;%MTun~8Z-gTkf>0SnUezI zmgeRpmXUk>GbH8|l`tgcr7$GsW#%%#29qJl z2%O2WwL%jM@{3D~@(VIj84?Q$7!r%h84^nv5=%?+89=$QI47|<1Hu9oj||{NPz*^q ziOJbuALOJ$IVqWmx%qi1P+oCiX<`vrDleNMDL*HL0X7Z{?lQqzbdYff$n<`3B537N zB50%@p%~h4LkNJn>d+l85Y2EYP_quUvpFeMp*XQD6=7>Jj1O5T2U=!Y%n}b;9LbPW z1n!+DB^EIxmEN zQ!!{GMK%Mto6L}$l+OUS4s?J617!6KXgLmqnVQ0ooRQ6dlxC81au||xijp&mix`sg z${3RKb23tjKoqz~nF3R4C3&&tphQ zOixcOVn_icsFcJKhLqIwqSVx42FTn5LrP|1YEf!&W-&ubW*T_JqeKC8&*8)JDZvUS#XsM+2ajc=7vQX=+FjSic0e!O(%k;At}UaUQSM8 z5kpFT2?O$BF)$7+6!O96$bi7j9vq=+FMw09{p8C)H+AWeBQq!;8dKzxv1lvtUX!jN8+nh09(4W&WHo#cV~ zcwpx!l;ksHsHQN0MrA;iQfW>iLqURYDF`PylBa&?G-YMrL{j$a$cl z4u*{UqRguNypqHmhK!Qj9EOa_0?-*V(2Sl54d6`V0M3L4a3(B(Gn4ZeGC}^z%muCO z$xSQ(RngfDnYrl%p17t3aAv3QG zGI0lv572olpmpo{nRz7$slrmwg2MbfNN9k@t3a!`S-?ddoCit+$Q*E?3|i{Q02c)< zD@g@S1i?j6z0`5jqiO0lj2GEjAkhe-w zS>VeYkp-bk92t;i8HMp+#UmXiP9aJCz|H z+9J(|m5HF>&Cg@V$Jx37jk~1fmll;|Fo2jDi8*Nupq?&6enClIK^_BSQZ$DFd^!{; zu|ZgnK*CiEgB8P-V5xt>3Xsw!I9H)(2y{g_%_(3gNGwVO6X4ZB;9@nk2uT3$7LX6H zXDpBr5Z!RaxN;0aDUuh6F&RlY9@^Tn3=KocT84B_XK)Ij*ln;v;U}+K3ltDgI0i2Ve&F+Ho6b4vb z#Q-T}!Rx0Pz$E145Ef9p-W?f!ZXgDGZ?XW1vwkh9dCtK?X?k z6-M0bIjCWFb`ygbk@CQ3PVvzK^{XP)8e$DyYhVqM%?F*w2P#U6lS}d# zic`TWa~O(Kb2F3kbMiqV1w|!A4A66oAjKLerXY)zK`WVyKvRdf6o85t9C{(?5SPZH z(v(yNkPkrvS9!^)psEA3WdeMD0@MR6pyk>OC?cTdB||YJP7qCVNFTU3C#8s?I0tl$ zi>d~!ivc@;6?%d!Lou{EDb7zTQGhfw8NlO;4A@U|DK5y&V<;}j0Yyx40k|WIlwrV2 zCb0WX2a!Eahea_*^S2pm^@As zTv8$Z;!IHD#~OmJkOQM|xX}%CWRx5D$S52tJfO$HVh;nTEG`eiq(P&(;6WNyTAyW?nWfZJBx5xLgm~p@~ylafyOwNop=3d3`2fegL=u1L81nLnO8l65AMw zZGyx$MPi#FvCWa#7D#MMBsRFYUW_CF?ngq}1qc^G+F1xbxDkfnf?EX&FinV4%t4+) z@Ic-|@IW3z@IYQe@IanJ@Ic-}@IW3!@IYQf@IanK@Ic-~@Ddro{bWcn2pOCPc^jbs z#p4KJnAZ^^c_=19g90Iq92lVfICvNVvesHP1+=h~0Yju1A_Q9Rh}yO+0kwKdl5!YI zl0ZGdlGLJH2GC+HmZB8!re_E{H8Dj2!G*U$!IFsfH&`QRg%W)B6Qlqv04;tIDnOY- zAt^tl5+MW{bx#M+sDKu8=NDm>Nh{6CQOHOIH8Ziw7nfuf6y&5L%N3`B`mBEN4$lxKul+3)0)S}E1WC74% zNfL6zf{*b{MkoPI@xr_N2;rQ>y!6tSjJxECqDhJshj$JM@ zuNc&4C@)GZK$r5pca)N`Mo$f5jlN;`eN8J09YI|{X;rG z2$z8lbVcIjCW6+@CKezCL2-UgCQ{A@&v1ce!{K?bxTGkxBsl}gl#-&%Y|xS+@VYx> z@k$hzmm;MbaGiosikzfMl2D4Kk|dO(3FHigl+@&W$mUZdBR~sFi}E3B@X>^eGZIsf z6Ew&WUC3e(RF%4*g#;j3aPf}HDMC(wr8%JT26QEm+s(Da~LReS^J|qXJ zH~`HCfCn-Yb3hYpaCelWRScl9dW10`9(YO~NvJ5X0KA$JSqO5*9%wX^p(H&AG&fq3 zkzbU@P?AxU3R-gu8rUmlfJ{?^wv>X{1q_f4kqjmI&~cd((1G#bnVFKJRE83eR`4(o zsN+!rI`k*KG$*l00XiFle4heCNfEe4t|(zBg-+6xB9Bm(LPsb|6`-?VFbZ_CJvih_ z^RgLA3m9O*1ZRNOvon;H7ZjB+lxJj?q{3{6a6pr+IjK+?Nar0Q0qH?Al;@=|ROl9G zB!X7OK;2ylbzmjTEtRQx3;{*?pfh=OJyUeUAjeT#DM05>xggujbbX7{GgEY(O4EyV zL-MT@GD=Dctn~GhO4F-AbI*G44QKk`S-kk9(saG#^i2DLqWqN7T2m7rKH zw)Hf$@YD7&H1JacP37k2rRJ5`W*S=LaRvD62Bm^3kNiAc(1K+v1tSAPV_gGdT?2Ck zBLgdA6Kw-a0|PG5Q9QaKMTvRE;H8FE3ho)Hl|`u~3f`%CS(yqp=@70%dTwH7j$U$p zt{s;Tv}(}}NlnbPQV6X~&nPWY0G)ddI>bpKI5`tEkEGxT-Ma_c%48Gj?dj!EnV6BE z52_0bicw9nQYcO5^7Zs}MTDE7o&k8hQEFa^Zb)T8sug&zpngG4VrHH-I5iiime_`d zxanFT)PcN_mRh9inwOjpI@RAw!6GTMgexEiv@Bj1)YUGwQphU+bBk>atwAfVixP8e z4XnAqmkHficC+)w<{PVScHC@ZP`K50d&14;o1HgSVP`TZ+*ozH?RNL=sW;m|>OkX7 z3OBoMx8H2K*?D8*%}x*v5(I6|!+PP+t$nwr-q?6^AC_BzZmhaJ;l`$$Ew`uMSaq`% zF`plgOeZ41zSLHby)3qleF>Fv0& zQQ^j_8_RFD+-$kA{AL@-5G*(UfNf~LvHA9dn=K5g8lbgTpnHBm9e*tM|J+!Ad%~^t zH#VDHeB??G{s zq5ulm+ub1J7#=nBKWgY#O#!*KQ%QPaef;q*?=XM-EO}H3bu`UTnsn&-R`)t z>UPJ?W>6g7S_`_B0pzh88*gj|rTQDIZgwi%Sa!4HW)nC**Wc^}nSrVVd`HlY6*oI> zY`NJ2${Zjipc8GtzHR}fkQNW{l;dH(i@vVk<|vx9$RiU z-|hgJd1KSf&YN8~mfzS24kARN0!20?VS$4fk?`>9!l9#B0b4Ryb{kY=s1{>bPz=sj zH`al3R~Ptlp&OfTqqtp@LE~lGhAE-bArIs5T8E(u6L59PP42PQ-4!1EJZeTdv%5b=u z;cyEB$Wu2qfub3lu5Up~rp}wqps>8v2FeKvph&#g0?J7sCa8#O0cT#2B&h7rh!59f z0LACcHjv$*u;{qe1_~Ka4)3_J<#zkc)?012r-IT<=glTi@&QFLsPI{Tdn(8~H#@=B z-&l5g!mYNOowvJhPXMWca|A$Tgs#21{?$i1*WE0J#k$53_Rx zsPX|F9s!F|aM=P19#CC_Cq_Xz2V~IACM1hA;v+Rt9f8-M5O;xn0}e)zgF(iDYNnf= zH}}E4eS0eS<|ZF783gtOSOcgQXad!u9iUvk0#rYO0#pyI@#a2I_6OSmDS1FS1f0G= zfqHi2?h=Z%fG*5B^9vFUcl?QW1s(3n{dtJ|6&M%>s8D$O3IZfpVRhh{2xbpx&d)_`0L@-;-^Mm;WY#%_c73mnil zyKYYaJ8kpLPEaCH0OyhxPz7*f3&b6_+iz?ESq{sNhgL&dk_zzarw;7~RYUDJyKZa* z1pz!fZg$=Py8)C*Izh<;6nx+UVIMdmw!jNGgp+Qq1-k)~??8?RI}1|Cfh!6~uDS^d zgH1PEL16?oYa=N0fg%MIAK-HK#>U$nAWuMYi2|k$a0uXW4k+<}ixliy@wpUM9^Bk_ zW8=+^TkAnFakCW^tPJ4B2B?}@0WQuI40UgS3b2i!z`8vZlA58#1tcU^-Rxwz0m+%5 zYVXD>1+a$Apa$N}ec<$dvl+~31Ep0^3k+OL-dKKfAGkf*3QlF6pjHBM_0a}Ovny^a z2i2`NmTScOXflB6Vo3P}@*F4!Z2`3iZ>#{d+Q3P#3shRJzdhl`Mv!N2wt-4oP%NQ) z0~BO8+Z4b-*mScARA53=0VqCiwke<&u*+_CfKyK!I93$U%UE#o0hIxpZ!EtFE=O;6 zL5tkYH#=^&K!OU?{_bP|Cw>sK1LT5bHO5pZXu)|wGB^D^`Kus`kYa1Lf zIOHH1Xcs66g9=#qgK`1Q;8sP)%{Gt)@Uj}z1^@*uxD5d>NkN4iycUPFgTY2%@hqsS1lPvk5)d5! zpj3aelL69Z0CfXEbs@-h(6|IBC*9Z#vi8PCa71rWfc3y2(W?<30%}HsvMKh;9#s5* zOavv3Hc(R^R9{1K52y=*QNM#4$x}gbbF&ky1*Dv^>K&B0K_xiEa#)H)PtvFr6S$$c z58R9fjjVtR59mHn_>FX+S>_#*ud!`)IfFCk_C8b>gPTHN z?QNjM3?80<`3BUm?*jD_L4^;fvc0hd)R~niw?n1s?YakU-r4P{@MZ+X{6R zOb?{h3+*z1y$fn>fZ`G~ghZS!aIp`rR29JGZ7ZzcQ~)IcSX&1ibJ(p#7=Y9|LNg1e zcCcmONCX#Epiy_wm;xyD@c0!p{0T{@&^{HkD*?*lu(B6qC8)zkOelcbW5}fetS19% zH$cXWAz@02nUv^-7L1@IK&% qFn7t#6=;RKmO0e9&)fg=|*vI(vqH9#kEfhJdo zh$E!b14>=s0Yai31M1(dxUmT|$oQzCpY*^7l|YcW8&Hu7&l%th4)q?wzhJL{b1G;Y zA0hRH?^+=xX0= zfdnd~F|-WSfkdu9nm|JzU{P@Uu@y8S1Qxon{8k&tj||{pxh~LHEU2ds(Yp#-%)w@j zK(m`Smg_Nqs%3EDxGLTpnPY*(Q80&0)>$ZM#JgyM{M`vM80318R!C@qnh)?vTu?U> zJh%(4*uV)CKEDa_Drm$WJgEiEB%p#2)Y}17Jk6l=37W*kWg@)g0?I1TjuyB>glPh( zA$(&ae%F9|9Iz2DP?s97n=nko=9j-g-Qi*Zx%HCm4`MUerv6j0^V^raGpT730#7K8y>!( z;V_&de2^v~D44)AMc_<^&>M_bFIX|zUV;t)?9&C!FM>uxZ?-~`BdFvD84W6WkzxTd zo&XA0q#hb5je>eQAocLUJkZdIM!X})?V$7qG7psJKnVssAAP$W)ToCfM;w~nG(k;5 zxJB4H09dT_23bi&zY>qDeKi@tqggFTy)4j-8nF)d(_{d(EpKcA^>)GOauxAG7DB#e zJgFI+@ImW7!0j~991l22(>DH5+(TUUYDVhafg|_En%kf$-xg4p7&M^_9WaF$tq~8) z9GLpRGYTll5vC^`oI*fDHi(`i*e*n9K$HCKsR~$42*PCoWEvcc9%vCmFc5Awf+voe z!L1z7oCb0i7*B42_zh|cNgQhbfQ~gb_S`0L73LZ&B_Bo#51lPsT z>IgJ43+rC$F~9~B!M#vqDR3_v)?NiCCu~jyPtT&w1cC?kA&Nn(13)DwycfRgb{n`Q z0-75|oi+iF)nL`70G`?hhb?qY61Ct01vY5r3=~$Nel2L-60}}khFVs`+clsGW>7(P zYpov2BnD`ti|_&>uv0eP?7Rh1Bb2OG?3AiHk1K^CLk zSOuy;K)zK#Z_R>&3esywcNu7C7&O)euKz);AJ6~?VP_a&Is-bm2bKVNxd}YF0B&`G z8){I4!OjP_1i&-A$dl72N_Q&2dx+BMi2G()rEHrO?g1coaS zLzz4lsRk^%z-ubNZX;I5GEmyUtpja3160O<7Bhj?XhDiM zs6UY1g{J2QwgF$FH6sSLkb@16b+A?{C_b?U0=n~%GBMhaE;v|j65&H6BajA&p>aoq z0g#FYw7iVia6uj(UJqIc4Jq6}Z5EtH;2Z)*ow5QIgpd(ou>Xk(L$b7hm-a5dxeqkc z2klTG%~BC#Ey@@&PH&^dH@HOK2=*EgF#|3NK?9Jjpkf3xbp&aqk)#!D88IG$tlWb% z*+7~=qnq&cq#yz81p%55A$2Fx*m4uD5(G^ncu)nr3KmpgA#xsUks&dj2G5Ry8%sD1D{>zK9IIG^4m`4lZCDu8qMLx?MeG2B5!L5!)V5nQu_Hno6<@IVWVKrNBY&>kJO$i-C@V;bHHT4)H` z(g6+!;=-Sp;uwofWE994rVv*oV`w8#C}XH6rC7$JnS?MUvuMV&9BtkYXW5LY6RDMf zoGtN{&X|UP@@f}}-Gnp8*$aN-o)BrS1176Ao zU2hI5*%Uxau^?j~;MOr#cVagQ;RetgAW`O^Y5|RFfx4ie>az*be81TS3M^1ufrkw! zZT3Kx5`dEwz=1Z_bDFJ*!l3hIZ0>R-q-7^r4hb9*YoEzr(S@TN_IN$JhQmD!hx-{kgZ+bid=-pQ1_=}(C+LB~9C>{!W51w;y9G3621=3O-C>|A9a8#sffmn$gAr}e z0(s;dG-m)>3%3ijauI2886gg`4>T081&fMhpd~&?^E{w10PhyK)dngNZnZ(mnq8oA zHPGN=8)Wnz(pJ<{0PiA4n@=3i75NUK>maF8$fMdOs8Qt2Q{EU zyJDehG{8jyZ0#th=(#D@9svcA{@b!81gyhdH7S-K`4B#gG~nH2tszo|myrF@c(spn3>Y^@AHn zpmGsBdI%c01`oD@vL0wZEy!5#QUsK$0JH%NG4=+len6s#@iin-xy- zi7SX9E#PI)ptbX$**S2AZv*X82km{kJyj##Uy}iPNGNC~pc7QXg4#>)!Ur@q51Pp8 z0tF#_6EU~~0uAwlR)~Y#16pMUDpWxU3^YOs%ZZ@m4BGPsN_^l11e$IGMGk0G7pp0t zlm$t!kR~Bcli*wQ+dw{TyRiwJg~1gzc#-psEueMH=u5Fc8`Z&Uoj_3yE?z;aw?Nqv zI#0vkn_7}+!~ih|P0=b)n*=nBb7K|E)8J)bpq2wT=s=qkmw~pFf#>JJd;V{BB5%0~dY}U6AAe8kmJQ{y@{> zpav3nqa3t0fHbYpm4McTg7YHC6hzSh+Di!9S&Z7aM3oQG1O*6a0ml}|c9AyFf^O(+ z6xtvZC?`T@G|&?=l9{j_o7jp@P;vkV6{P(E9RZ@Av7qb%YUyArU19sQAYB^Jj5#RT zBKsD!{0@{dVDtBgJ*8;HE@7j<5evzmpjr)7j6nj9bd$h^HK=I=S>pvsR^VcoWV6ts z6IO47yLY6-AeuRljR%MYe@IOQQcMMf8A`e!+kF@&QOSj%9s_8&7qV|1TAqT^G$=d3 zGZ~@)K#T<-XIO$61iv-#ybda#!5w$J)_~@IKuzl#n?Vi*FIzzJ0%!#;a=`{t1NIEu z7PJxt?087460`>iw3iFH^K*D2gP)_XE39ui6_jpoYymCcL+Ox$&icBw9ZZ|I$%G6HfBJZO-SWABCr)8Jr&T}MbM!%*k-P<*9f4l zAmp?MkUg;JQ>by!<31qrSO@E|DuhnXfP4tvSd3x}O7jA3P7}Ln;5`uFWd~0wo!6Wetfv(5enlp9R#72Tc@#QUz${9WxNYl`m+J5j^t;szf@mxdllX+y+F1 zLpn(iKZ443P$vU4y8*JU4XbgWRv=>P4yzK#NCY^x(8htWDu;J!Kz(+UiB_!2LBj&j z^O&&8gMx(Mpe`bav8PZ_c?DWc4q8`zV-;vYDCD3B_=q6VC@``KAYte^E1+H{QtK7e zV*?FqL){GPbAZlb!jh>$i$_2K2=YuTXeTMOl?K|Qug3*$p@9Y}LDAF%;=@}$pl0li zO$?yZj&5uO9aRKg7}IroDtJr?ZJ`SeRp=u}ZJ_xh471SIyx=ekb<_-H`6akF14)zE z+JiSi<3`ZUvY_!TSWm1K(k#8%2F)r+!3{a&1d{wZZ#F@j^Pr%EjH=v3KF9==NpGzM z4IHckEgAx?7=gw!cqv+&9>d|u42P#M9G=8*cm~7asSJmwG580Bc>4Q6dWPUtT%a~S z==cXvb_GqYfg&8aH_#032|!z$pa=!GqClA%T$R9( z4TffhL#ts69KoxMzzzd-kwF8S@Z+;UCp&=0zm|db!a%oELu)c{EVMvMFmOi`bod#; zof#WpZUwb$LDe|8+XUI7gRS)e8Ww8>mE@qIUXTLN$R_xV6lk*;(>!dW6R@T*TAKyE za)pkEp*I{?+(w)y1PKr5;;If%o`)lkp93^B<|S0|y6eH72xc z18I^&I-sDf$z)pw4i&O21I;Ob9Smw8p>A-1PI`djvK8!nP@DF~dQfZRW*4*%0CGGi zox|dQH1j~E6!f?((1;oiGYN%0N^ONWS_KrD;KooJq`U;R13-l?s2l)U+yXx6Y#(S0 z0Nfvhw5VY!zztdu2V7r*2SiA72lns3N`Rf3wB%k=qsQs`JG=Kyunn3eB;N~r;JigfpE<{izLG2h&DuPTB>;nyV zK~C|2jx2!81Z|oF4T&SBe8A`Rfg1YYF&s#X4zlq@j{)zN0zHPC`#|md8(Tmn9cXIKDR)}X|{l?Mszh@pb0OK^`IoL06tG|`?LtbqtnP*njQ0tXE>fzNIQ7Y^`4(4h4vIDdhv6hyHP&L$y=Ns!K25csAm zP*Dz_r-AgQz?lHHEdacr96rnesuJM~UkG`w^Dh=z)Y1EX_kYh@inn*k~=X#TWzdpu7Powh&`?pguNeT{L8r z22^>1?F4l?L1x0D6V&wrC1%J;r(h*8XF($abYc}~ycm=vK&MfGf&}3*NT(F657lUB zwFb&QkT`)fj8Ko}1L*^01z0Ny%LWio{6dDRz|nnUvmOJ;TZq$PKzSH6tOJhymK&f` z4k0@VXe?4S1vHv56?9M`q(s0n5&{|D1|{weaM`vQbhb3|`Nx`8psWX)18M_hc8JAo zpb!H^94Kpp779Qk8n$!;yb%nP5I_#Qx$h>p`iJy3klO>GtO08EgKP%ZQs5N332A&0 zPumrgTp+bE*bz+%&|?`JA;ShxLFD64U~EVZRk#5v$H65K$S2TF2f@h0l_c2GQl7Gr=)H&77+tq0ILM@WS{IJn>j zYsC9%(!f~IshSY)gOUsKXbZUO0qOvO*B^ijcu4vJ1tchqAr0$6QWH2?DuG%npcHm{ zsuKDcd8n4bhZqPL2&!?wvnQZwVX7Gl?y@U^1~S1h2syflJO_fZF(~aQfqIH4rosAy z;E(~QPe|hfrMd;34-73qKm!U>K|AB1$F?G+6R;7W;d)RcfP1r`#sz5N6m$eIs3!+g z0bWG|nFs~N>8jgPK{NA^;XRPALGcMb^a*MyB*|iH(ZXjlLH2?USOpz`4m#`@boer8 zHWsuzr5Vxm2c1X{?pT9H)j)gCpy!;zA{gvKQ11)W5rHDvWSMttr7p1xN^# zSy8$r$djp{VheOQDCE#`xLaY@FzDuF7MD1{Z&`qxT?J}^feNLYt?=RiR4F5>+8bM} zK!>+>fE0m7(?R1Ht3apFgPj5iA5e7(Dm89EyAU@vg3g}?4RnAGa0Ru&K$SfB$SF`o z3aVs4Aq7eYZJ;$bkbxHX0cs!*f>#@XR^EWdM%P2S*q|{A#F!x{b%16)Ar&X6Z3%5N zg32~AYPRE=Kk!yEyM$r~FLKnMPpYo_Rcx{`t-h?0U@nBK;3JGNSdHy<{&E*^g#B3DqWD|7Eo#e znYQX?2PkiY8Y!TmE6_YSXaXKoRe_|T860$c!mT!NCV|wCpb=(pasn&d2Z^*zpspcg z|2yPRYS3UGYzzzJdC))|q)7xh&;;7ggeiff5KvPFob;iS`jB%H!Fi+;yy+C=K2UW5 zUm$=!Fa$a-ALG!sPKY`1G6Q__8K|g56j6w&TSyEdx?mlkA`@gMq@sg+7t!PbmqB2U zfEyf$#XO*+l{cgGUcea~o@a3-BJk)9sHX-FIPg{(P`LpLLePpm#JWPzIRN0a32J-5 zN0^}r2-M;ONn+OuDkngB`1S;FOB1mV6QRutwn_t(guz||k3%BO``lU!IoA%<&ITnT zkYB+S2sj->SKEM3i35!c+-w3(nt+E2K`j8dFBMW!lSc;QCdfMkjRRGvkT`?1u|Opd_(*BQEfYj&c!vxH{-KB~Zfghqx$U`JQNFfT2bgYJflPAz15 zz*TR@EpXEw)-{F>QGzmvM!YxZTu6in=zLL-Q$RfzZK?HZtCSHa^;7@h#Nh(LEsfa)4hK?8{aQ1Vs)Cw=5j59qKG zQ1l|oUC2iIRZzE+(wPHABPbHV_O*ak=0XN}K=}bQ=?ZF6WBLi{q-hMFfU9^=c?7Bu zph+4-5qSL{C})GpBizkyP*j3*@hZ?_L&$szD06`pRzb3~0%)Zx=m1Ml3jlh08b$>M z?pK1UNpK{hkTyA{I-XuA$W9DLmiI6$z(31o{0s3CA;73lf|Pzww+5DQs2 z4xdwor&rLxa|bAdZ)_wYvp^yMG}F)wnnD9LIiX!`P+Vil#NZQWV53H$whJ_M;>uY_ zT`SOC1+Yv2>N}E@L*eFtM)NQa?uV@21f2?Svqb^I0WW9;7Y?wN-70L|Hq?m-l!_3N z7H{rDi7==`z=Kazn{0s`5^N#lzragFOqNn+eHW;Gs`w z3lcPl1rBa3t^hUVpes*6Q!Pa3ASq~(BMQ_J1YI2mItHrwX2*^7kbO~L1fAghF=NKo4f-fDsLB|v2&_$~*;R4u|^AW6uPtj+MwYR9cMjrb@~ zy^LsPgB%Px+X@moprHbI>kG7s12h5+Djh%tGC22u242Cb5o8r8s&BTEnA1Q;fv!;l ztzH53uVE1cN>AX(g$@S5x-^7R2iP^x5*0F^h|LsOt^?In&{i|3!oC5WM1r1+2~Ojn z;JC5e3e>N})sF?GGw_un;4%(;Uy&8)SRBx}Dd>&J0o3OKZA1a(oZA?UN%z#`?0nFi0_Z+1$mkDv#t1Qh1!@n0YF6+mNRUn` zr0NEZVOA?K-xj0BNITu!*F;W19;qe9VkPC zL_iH?_z3Uqsi2jZ$b&8z;R(_Q>R5sLOQ4%9Ti|Ui$S5^v{2t!_hKysQ4fx?v(Fu}+ z-jE4y(}A|tf!p+;<{0?!R#3=+&K3nVP^=U{7gfOT)`F#N)V*BLpaC_!5EDkK#gP6d zsFc333zW-YlM% zJjnw}xL|$I1}C8ibmbJNU_>+JMh_@tanJ06Di6>VVjzFuF-8y6XoT)K0r!`n zeN{x5XXNLmf~lA(udbf&-N1P!k8J2?HJs1vwC(mqF5^1R59x9sLc?a_hkBIw5xhL#Mntk;@~@p$E_)3?%l! zi2+m*-UM3!spXnLt$~|}whj1zPf&vxRP2Ff;6SA-sK*W&Fo%kQ*YILF%pB4zBdcM7 zT9ZQx30Tt^Jje}dokP+Is09d#Mes5sP(nlG40xxt4c2e~HGV;#?X z0WM##XhXB@);>_<0(2KQ$eEBSC~z=BiW!i!PI(T=$jV*}226!+5XU+tf3^EQ}Mt~{| zP&otY?SgNb()Phwfq|-xEnts<^4dP+xm!^B#hmd4m&}N&4U`fv3Up9=7u0Qpwu-@8 zKq&&0&=J)N+|6JqWJiF*a}%ib2KE!E8!`bjjt*HA2C8sei<1)zV5^p(ZJe9?;OBgR zv|)4EjUF^--RM#905_jNMK!1ja>d;Q0*!8gf)-L5gC{FM4SGy`sae=gh5+0U?I}n?|OGLr- z7^p~sc8VeE-W0%#-kLzy6+qNN1N_!nJuXB71c+Y*c8l(9?(_nAUW^>(V)v@z(eVqVQV_zy+TMNp=1Zpgb#R1AC?3``)p7;6ySUS zDpWv03UeUDBv5ptt;_=@FmPWCJSPrbR|IbEq0X{EN(oSv2daBv9T8|J0+La{?N?km z6xA6JJ3+lxP(lU`%Yesqz*C2)tt?P7YzJ2op#C^$ksj1C)LoG%{>O+Mh~Gh$Qkut6 zy#Z=Of?7+h;4vNW4ttcTTs@?^7dmr|w0aw=6H@7eQzR(wAvbQJ%Ne2R6idMXD{??{ zU!aj`P<5yPU9Sk9+5`1#z;isH&MT;m-UYe|8xqOj$vRN4e=6**ZqVif$XWx?a6QtF z1W<~)*$nP9gZk7rHi2tz@X^)a$N^tw49c4jS!9KvLJ+iC3>4AeYfV87D9GtKX!oaq zs$Zl7h`_VbprRJi^I^bWv4F}|$eJ-&4Ym$k3P7fcKm{9Ukl@B9#IP5nILD<5G|X_b z<;E89!VvTdA5{{qq6Oy^=z?s}-NYTBS&|#e74*SzaRWSy2f8mEG?xn+2Aqntj}El- z3|SndB<%!U)q;}j!3iD5xhJ6Df;O)}xdxxo!*dyq?tldMCh*u7w0dX)?GpeMZ0IM@ zgW8A4w<5vDQbEH-p!P!t*fvn<1DaX_B}!1a1Mca8mb%<*(}OP*2B&+NDo|erlvlxy zxZMp(OrRM$P?-)g4Ag7`B_&Ws2H60<5CL?CF1T^p32L!{T6&wo8(KhveXZC}A^{ys z137#HJj(>?K!B&FK-J6bsi1TLn(_lJ)di1=g34En(Nsukg1H`ZYa1x$Znl722~i2E zvavf1ly^a;TnD6C0BXsBnvMlrNH3{ zJ}Dg((4c|O+wGu;0e4?OSp=~}2iZfg`$VBLhoCMExRnFS1)yvP>Brre56Zt_eV}q3 z-0A_P2Z%0c;nWP;90O{JgKkU!mFl2^1+~BjjnRS1K~T_wOFYok4d81kVXXmBe1Mwu zpbB9NXkP}X`2wnUK(i=QZ#L^O#6|n%8N@QgMMqW|#=<%lP2d4FQ1cKz+q)68EF7HJ z5R?7T%Y8t@6VRdyyo$k56K$zBRNZaR8itM=8^LqHpe6^n#F~1u1;z%gdT@bXBHl@K z?*>%UfF>b99cS>dFrXR|+7rc)!x)ykg^!PwG1A`UUj=2 zWC-Zo5_izOLEv%#)XcxxdK2lqIdI93IL`;n1r#Cyag1H0ib0UAV-5T4AR&WC>cWAXz&4g*kU74$_KaS5c?)T9aK;` z0~&th&V;43 zPLM+IL=UKLSOzKpG~$Cm6J#JZxZe#bgup8TVWZF>1(22>cytWZC$hq}{2ZKSL7@za zaB#PN6-X^w;ss?cP`?q}Gyr)qSd#%9+fAU>2sk}JMn*x#LH4A9y$r3^z_mZLa@h=u z7tqzyi0U6y(RG3fYK{0Xu&+R4MxZ1ITBisvc0kv1f!cDQtOq*RDO{5wQNciD6uSGMNF!Ac<~GdEF3Ay>glAvZHSRYxID!Ac=7zbrL3DYZyPAz#5tA-^~| zu}DXuK*36(Ah94(N1;%`N};ecH7PY&N1;f;N}(t}H#J{Jp;*C6p*S>UpZ6L!zJE@kqq4CyV;7ggc!Cq3_Oer8h3&ZVj{0}1H}e-S^-qzgGPhEeg_p%pjAWbKqIE$ z<{_xK09B`;);vm_K$bk9+KWC^2r>%3`T|KQ+KM{RlnAJ51_wO+P!%ldk=9IuGB>DQ z4_X7-1TMF4fGXQ&lqf671EoK3hYvM99A3_loR|Y{gd(3C3c0YZ2^;;k7A|NM5>n}404_6MqCz}u_ZK=BHi z>)r*5WXxOyZghgi$-y^)-E3k=&d3J2A2c!1j%j9cP7XtIPEm43aS=muUKvAjeojV8 z5d)}E11bSQ)hnptx!DG4uXNnl0!pHg$=p?7--Fr};2~92jm*51)C$cM1#puMG}@z} zs!@_(l9;2Jf~GWu0d!3R=$3WxJ(r+U%x<@XwsLL;&-Qh~+JT^K2ijXW^~RPP8x?MW zwh4n)$~WEYWJoRm#Th8wYy^!qY9yCrl;&iVYAWbr>{tXf%s|_VUBB=9^JdZ>f;seyU~Xwd~4 z{X?3=1m$^nwGQgQF{C7xFhF*nf!fdDo8(~)H&96lin0z+kpmjugbstO0hL`0DVYTf z(8GN|ae`O~4Nh$-Iq9HK1C_ieE&}y+L4x2}3Sp$zgJNhUxl0kRzksy3hz2`x>@aU^zAZop5Wy0H=ICRwEX zF!g3Lj0Yb1K#Ozuv>T}5rT}gvZvlnnR8R&0-S`LRf!ZqI4AlwBv7I+IF&tjWaCjBN z;S~&rS2Luhlq3}~q~<1pcM^dLUDVW+nwP==JvkR++zB)yJ^@r^f*X7AlYc=jLLS)x zNGr-^NGmDAw&^sz09;T*N4`Os z7Mz}Mw`1f;hz~$^fSUZEF)dKf8+^bubjSuuA;!W$RqU;`3>m5^po_IYsTq2#4?{*u zUOEG)SiAu`Cku3d)6I?>Sj%5f2!MJppwV2Ax7$IzNpMpGwB@P^w6`0yAP4MRq=Foh z{6Q(0A)_Q0Qs01T%sS4zso8apR#Mx1DD&NVhXf2=Eid9VqNeGP0(T`_%0Br$Y#(i zFH{ly4paumoDxvGsS`9T1M(gNWbZ*vQVzK0z6l@X0#&Tg`A*QR04RfiXCOiO7?hP9 zb4swa3!nqlpi~1cj&Fke0A42mEha#170_B_P|F8q7OEIzc-uKYucRnH2cI2~k_J^X z*o~lA0@WhWIvMJw+|-gpJjOvg)7XpyhY=pFpb-Pm{5`0@y#?l}V#umFh=WQJld$Or zl~%XFt6RZ+ZwM13|AOKiy-y7eTu?YdCJaG!9ca%WXs=8sDE*?AZ;<*Cl#D>>5;V*W zI*k{!;I0j8j~%tz0`+jA)#@(LNCW6J1hALE(+IFdWzeZ^BI;=*^B_(D7va#!s!qJM zEqGQFhZT^f6KH!5#8iwa2vXgQZXhV9LMk(i5C)e;D4|STq~UcVrlH7%ALzD3@Xl6H z%?45mYG~hVd(_YmDk#8byu!9_fa)jERuPouA*lEUbs^e7l@4g7BWy8jGs?~|P`L*x z?jfqMkC}j`nZfm7PF^<1t_h$q38dL9? z;2|Qkt~9iU1XT^7k;k0k5{8`OlFX7^hMdZx6i_X?8C2kbI>+F&4;{fnYe<4~H)s^9 z7342aOB58zt3W+oP)iw{8K4`lKtT$Q#LbZU0y3Tpu7W^2yjR^=&XAi|3c^W6AQI#h z@GL&qGvFi*3Ib5&2r-@^w-g*RH}^p)T||Psv4!FAMo{$%Y0|)QD(HOGO*dOW+aEyn zA!s%Oyd4ZS_CRnWG-AyVeE%-wG!<}kA?$};d<=>`$SNREeSdo@s09xyEj_9U0Jn*t%)HWEJe@_*fCFeiisA5PhQnJJ4sT*OyhEMg@K%Py+dwVQsgNOg)YO5c z|Apv&ffsRY1nvI;hZ-n_f`$UXXUj3<7nJ0IQUs_1-Uy2FoBJ3F64O%^Qu535u$IH% z$!OHHg0l>SlrEqV3&^+!Xk;I>2LQD+1Q`a}`9_M#u+kMNUf}0Ff<{nQ;VAjQ$pBO) zfvW+~*;1f0qd-v%62R350wr*mCNfON=2%Q4!NFcyfGyAq5{nW+P2%OCoCoPN-fRT7 zBSGaBqydS;!=OwHp6`J9k#OAyIvZ=_jpZ8+-zY0r9O~K}10{`{P0-yp3V7=yNR18JSyEI| zkjGF|4(ePV22It1Ppa4gY6gI;m~elc2q9H(NoC1@KC{jo@Mf zdP*>)$-M?Nb8`c{C@R7Gd_buR+?c!poiGFi8nmSh>RY1aBv3H|DxyK7 zOYo64hT@!*A_mZjHKlnankfn>qumAh#hE3U`FWZt3c3)(T9Dd*ko*DO8q|KX6*O@I zI_nf}GN{=P9oYlb0ymq8oJZATC@#p%V<;}j0c9mf2!RV@&|nW}dKBEf0IdfA-EadM z*alSuQ$a&OplJ-yzz--5Z35>vY|0L4%Jdhd+Qh;NwKW)`3R_ zH-px_fTn`LEqZW@+5{R5!FFdi$Qj@h6K*!^f>y#pY8X(Ig1X(Hk+yxHb}MKA26|;I zBx8aPD}n5(MXGE-N1kb+1#}YwvXW;4&6wpwA!`%X!>416(!GwAj*ZKAcg`l3r z)SGSa5lzT(P!Q`u3wA&*1#RI2sY6-H23o=dA032R2hMEZP9G@bA+ws`Q#Pl97ld|! zq7$58KudEWnQjw!(g_@xNP6Jrp&ytIZcl(KbI`hPkg1@K6R1&&IH?}48B{Gp^AcEW z3%15Fs1S!tR)CTLH0dD45@<*o)OZ1vfY9~|q-g>wXgWaS`k-?^KmoQ2G&l%qT!D8o z!V@F35Z`=b6+>u{C-(7E&;TJgCqPCvkVhXtP64g+0o9hBkW=qKH5(|D(MMrHroh~W zJ$h~<7g+|N#D*+jh%R7+E?|rV1X`Ri7o)C8bB!?G?0KgDFPjH z1Sh?Xps{AqKq#sbP{=}?z&Frjz-18VwqXn_ADP)2vWQr+-X_h&rA`46*OSns+!8Im4u(RiJ(S};kcwiYk(d%tm#HKv zhoK}1G_nQir9esmP%{+VM*uZ2K}ikNBZ1^5P~icWf}V)d0xFZi>pvj@3Q>t-Cl(=4 z*g%Cr)$6Ubpdm$&MWD2US~($#4e;jT+ua~#pbi=+rB1!I9^^#ORc9MPZ7|T-9;!He zE)zWJI02*pbOixur5U&s2CWK(83AcWfERs17CORO9^iu*K}$yzUS z(FDqHpy@H#UN*bMQ)n8_Pj$J@7h*R?xIK=$w)+P<;k6WCHS3A;?V|K_i0D zsW4Dx1O*_Zod}+H0{aDYwJ2n=40KT3t+n8D8$b&^S|9_x;JHbJCXk~*&Gc2E`U-r+ zAb7kDa`ZcBwJzv*xwhM&S)xvGKtfirfa)H|STXpv3-Hzr&;>l8*nlrr#ZUwZc$BCC ztyYDMwShO_fmgYK!w5WN4C>8+rz}AYv<}dXM34yuh$p}+jvxtTE$Em5Q0oQcjZRPv z2k!2I`|c1IgVH2;y#r|U4K&;f>z{#Epo3P*!x9t3k>G1Mz)X+@(0YX-r-&h^NVg=3 zp{N8SJwOh^f;0fYr8Z=06k6kL0j-=> zn*z7NIbH zh)@k*xegkr1Qn=Q6vLKUfM!^stG3{VV^a>UcEE)VXyp|07&NHBfXrrs3JuV{6^5c5 zhN2u;;DWk*H#UR(11c}UxdD_cpy!IBBz(}aRG3`zZKMs|pf)^csWwPAXsEau+zkcI zDnbfa&}t|wYhXdGpN-H30HE9h$?4GJM?e`FHe&!P=fU%KkhWnHXkHeyRsq!D0UfS? zyZy!rP;|ml4|rWWxU0rclEhGw1S(oel5{~u3(8hV(8xKcMbr$+O(-&;tknf7z`?V^ z?V!v6auA9d(1?8(Y$O9oMi*Q=fOaozL^D?xH0Xj@E(&fvgSemqX(J?AfGS*2gLxIG z?*{HQqeKD7$DlLlAhOsa0c<_ERE35UI5C5JMxeb=pq+7T;J5}6pz#5e-Rq#L99+tP z7Gr_#e+9K|TjB8tImZQbHcK05^9yKb0a7%B7VCim476Yi+_VLcKy-qV1SFSj0k8T4 zRUROF8A{S~l1lOz4(|i`xZ_qEc&9XE_6S^<+}H%(wgRfRLCFgm&LCfa3M$aZJ$P~r zw95F#DoB9@inJC`PKT}LVkpUn4FiIb66kDUu=GYyCIy8nLrGC85oeKr&t?D}^$rRK zPzD39NCfq&P$t2^cQhcDt8HN@DFQbcDoPj*?_xN-o8jSx1TE=7HBk4Brw~ZX literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/uk/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/uk/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..dd63788110f102b3d81f5eb617211a901f056fb5 GIT binary patch literal 171944 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 XgT}DHGnn8tcc8Wb=qw~q8e{+fi!;u` literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/vi/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/vi/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..0f31ac8e83262a5ff4f0cbaeb1db4831aec5ed1b GIT binary patch literal 97079 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 SshdGw0QG}Gi)PoBFaQ9`WnRkw literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/zh_CN/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/zh_CN/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..1d4ccbebc4e54b3368035620e7889784f764e59a GIT binary patch literal 122370 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/man/man1/cthulhu.1.gz b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/man/man1/cthulhu.1.gz new file mode 100644 index 0000000000000000000000000000000000000000..41c7183a5eb73773589533976311a2961e1ef256 GIT binary patch literal 3041 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/src/cthulhu b/distro-packages/Arch-Linux/src/cthulhu new file mode 160000 index 0000000..5cbe626 --- /dev/null +++ b/distro-packages/Arch-Linux/src/cthulhu @@ -0,0 +1 @@ +Subproject commit 5cbe6267de285ae5a42c464a1ada16d6d00c2bd3 diff --git a/meson.build b/meson.build index 19dc752..94d786a 100644 --- a/meson.build +++ b/meson.build @@ -4,7 +4,6 @@ project('cthulhu', ) python = import('python') -gnome = import('gnome') i18n = import('i18n') python_minimum_version = '3.3' @@ -105,9 +104,9 @@ i18n.merge_file( install_dir: get_option('sysconfdir') / 'xdg' / 'autostart', ) -gnome.post_install( - gtk_update_icon_cache: true, -) +# Update icon cache manually (desktop-neutral) +meson.add_install_script('gtk4-update-icon-cache', '-q', '-t', '-f', + get_option('datadir') / 'icons' / 'hicolor') summary += {'Install dir': python.find_installation('python3').get_install_dir()}

      ^mQ#8^nx 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%0A#%m=-{T8ljc92+{*wz>J*6uZR*1)=-Djr+Ylh@ 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mr/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/mr/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..ded071929e801e25a801997e3680d51298a205b7 GIT binary patch literal 19415 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ms/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ms/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..1835d20e2e9d9c0061a4e6bc635a91d6aa44c8b0 GIT binary patch literal 122977 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 X2c2hDnyp*GPzm)@CCvGisd)?l&}d8n literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nb/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nb/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..ecb1d14b9ed0c7bb7cab191ce75a473dc8124cf7 GIT binary patch literal 111386 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 UwCj-NuT#zUO!-`1^3}Orn3@axwFz_%iFdUe~ zz`)DEz;JdF0|P$;1H?sSx{eq5Kx8{M4xs`!-EwV31;9U^qRMfx(=Cf#KOy zh<$R?7#M^Y7#Pf;wC6O4yJDdH>}d=P8Vn2!b<-FaR2Uc-mQQ0~P+(wSI5Q1m@7rk% z4D1XH4F9G<>|vV@;mc2FU|?ckU{IgVz`zW0FH~G_IwbtepyJL@arfyA3~USx4E|7l z*mMR44h9B>xakZG>I@7F>C++h^-qU{`vRyr>!vd>NHQ=m?4HiRpvJ(!a1|>5XF3Ce z76StV*9-;*X$A%c(-{!+17|QWure?(L_q1d84&YRW-u@)GB7ao%z%W`Iw=3-3pK&oKXWD|Tqe$BU=U?sVAwR1fkBmlf#JkV1_n6>28MStA?EVV zg1A#-76U^Y$iK4~7|a+L7_QA?V2}r;kJ$_i+zbp1x=`A3HY7e=p>)V>NIFQK&A?#D zz`!tJHUonVD1FU_gv^w+(sm_C>vw(S!@G6}L3D*hp7#L(37#KFrgQVB<^C0ec zG!GKK-=XTn=0n_LJ|AMP=X^-G1kPt*5N2Rth@THhr^WLj=Jm{n=wCG-5>6-QL&Ejn ze2BdU3n2aqT)@D<0!oJqAo)FK0VG~(7C^$GdjTZ9PF(;=7xNZC{Jm=d#GE?|ApZWl z0OB5ng^+xqw-Dl9qlFN0mxYk@9JCPP&YXpiaA;i!@y~*V5Pz=V`(g%JBLE`-G6 z+l3H+{ezk#vk1aBTLdXDLZJM@MG$-Xq5PGLAod(z1WBKd7D4RiTnsT^X)z>y+AW5Z z8*z&v=9NMDlcD_8P<1C3L-fB`3<(FuB@q3}OBfg|7#J9wmq5~S%@PI%T~N8Y1QPz& zmq5(rSqe#ino!zcDI|Q%mqOypbtxpBq%4KFuM^5&x)c&lrnM+Xq{iTrjdA<}9 z?jM#y;`7T=NcjI;3JDMHWsq=GT?UDFvtrnTgxHtd%ql#4>?yr z+@-JrB5%I}5*{HdAnGbtK=e;u0Wo*Y3P}Fnw*nF_r&d7XtX91qru%Q2OyIhWsV*X92{#R=tNsJh2c`tL?a{EKgbYFtxtk#6cl{=adpb8k(%;-okaWEi%HOmJQhw~(1WC__H$mKY4r=a; zO^|S4+zd&_GMgdsrMwxE?~FG?%(LGNDffIfGcaf}Ffdd?)h*r(F@N)Bi2L?H#m_Sk$rCYW@+}pPW;;)%oAmzluEfDt} z+X9KNhfx0CEf9A~Y=yW(bt@#Dm~Vx&oBXyy{1vhlQct98g`~sot&nuHW-BCIjzIO@ z+X@NyuTcGb+aU2NvJDd6CfgwH_t*w8KXw}={*$*s>}}WviRbCtAo03(8^nEkwn56R zliMKer$5^u?PlZckoH*kc8EXgw?o=tOSVJYdulr*+&^xImd86F^^e;Q1_omW28I$S zyzxpP`|O0MPumFzk20uuA5?tBPDniO z*a<054(^2b{|eNcmr(w%osjV1-vyCZ-UYG80?PN?1<6lwyCCsYvkPKx-!4eF&D#YD zudTZv<{W|YZ|s7E=X0p|U#NP)-4JyeyCLS-?1sdf&u)l$sZf5+Ziu_5?uOXAVmBmx z?}GA=LFpS%`W2M^12vy-55#<>JrMU9?SYu@xCaux5qluvn+oOULitsDAmP>o<#$8* zllMUK+Z?F+#d{#}y3Oa~Ykv>6x}G!8)Q4>&{%w2JSfx#BkFFF7T-=7B{@h)%>;xDy>3=EMB3=G}}A^uu=5TftsK}fjVI0$ja z!-J4?_w67goY)UR!cqJXB>m|hg6Q)-1SxM54nfjQ-XTc7YKPKW4?)t)W2nBbhaly- z@L>pT1f>HHL)=?%n1R8Lfq|j@FeF_bJIugf#lXOD>oCMV(IXIlYaD^N-~R|CT=Jp( zsYf90-FgIK@6jWW_`MEQ_v8q~yj~#>Lvm3`C<@u9ikob9j3=%#p$06oQ9Eb3=k3-5w`{R)Eu;@6%-LsBE(&OUe zko0mHN;8~*grDvSNVo={fRx8oCm`-_I04bW0Lou^0^i% z32`_7Nr<@gNr*d*PeRh6+ewK3vrj_mqaLXG=8K)ai8vKNIbZnhPWsG zG_*cF4Kc6fG$cHipN7;Q=b_@iPDA`7dj^u8oX$YvC+-ZyzTz_w^V`or`ako}K+2UH zXCU#!a~4vL*`I~D-|Z~K-6>}w{%$!73EydFA?acnl)wEfB%K~V3$gFsSx7qk4AsYQ z4&qLsa}f92o`a_nKXVq=V3l5dT(RWMD90U|^Vck%7U5 zfq~)tMFxgY1_lO^OAvdqEq^9KUvnfx(%9fr0xnq@Ce^88V*N zb{Uc%E?$O&=dH^ScfN$u-!DVT1=cH&_~5+);Y(eC=u^4^32$vE?Es}ip>)<2NO;sk z^)0vpN%t$RK+@x8sQBJ13=ED83=BuFFfc4)U|?Xs3dz^2u0q1=`c+8ye!L0^4~c6G z489Bu4A$2m>8A4<#61hHLCjrw4U&F0L&eWugT(KRYmjt&?;0e%e1h^>u0!Hm;yOfL z^ExCPY@xLGb;x*14vJC1l70fIwV}SUx&D3|8)ii(2(ni>kJILLF1A)7#KD) zFfe?&0m(nhZbIC-?b$(+_N_!?znOjV&2o65dXb}%Cp>ph;!e9*du%klD}nc zLE_K+7Q~-!P}&EoF6b5{+@qoT)1dNsw;=ha1S;Qf3o@?I4b|6w3zDyA+=7JHX{bGS zZ$aGq25R1CDF62@NIGG<4Jp_7Z$s==y$x}n!EH$Tw7(4r-&m-4_HBs1Dk$B4n}I=v zk%3{#ZHRw&-hs#;yaRFHxjPW?OLrjdxCP}uyaNfBmv;j0dG0~-g8-D)x(A7W7brg- zN>@U~C*Om(cilaRJ9j|M*>?{TeuwTs+;!?6B){Cg2Z^8W_aN>Py${i+aUT*sdiNpf zE$>6}z1Mw+{qgr9?yG{TtGf@ew-c&<@_k77EP?VjLDe6=4{^tFDF6I@h`%pG_1}Wp z|KvU-J-xaQDd!j-K=_gmAnwtJ(hd(G=`;|^PksP#U&#YVc=tbmlf%h&$Fm>ElrGM^JTt9zon8{1_5W8jm67 zI6j7$ANm;Lj-1C3`9 zq4G1K{0&bb?m6}p5>EG?Ld^g96cWzD&mgq^Gl)9xXAu7+KZDp;{0!o+&S#MDnDq?e z{2pZ< z{eBK{7yk>0yVPGm#LZto+~xfOqA%tJ#9c*DehZX8>jlKWYoOxCp!_>8AmQ=t1;qV= zFCpe=yoA_e2c`X>blgjby1bVVds<&Y%J1n=eaoQqo|h2!UV^H71=aWGB_tgQzk;}5 z;}ygl8z}7u6;F5taYqT1?s^4r&w^JFb2mW6PrQQIe-A4E_7x<4{zA-^BPiKoq7!^@2^hzKS24v-$3fK|8F4ec(u2X@ow+85b=_?5PN68h1j>~EyP{R z-a_29`7I>e4noB*y@j~{K9qj)7UI5_Q2CEg{=c`7dYA1TBwqO6LCjHl2MJH(cM$t5 zp?uqS5ObWN;@(hk|922~gua91ljL`hbX)Td;_m5C`FT)!%{xf?+Vu_+ALrgd!vD!T zNVxrm>f?G3v0v~##6P0%A@)nXhqzk_%GZ7mb?m+*|e$;@%#p{5+`sH6J1FKmHLCF1MljK753P$6u(qe4ilhmHh-!ulNZfZ~6&h zpBt18`2=xC5|l24s%!WJ3CD?_ApW2B2@;<3KSA8N3QBMP1Sw~ae1f?5-X}(7vWTJmRTd;2pa98Z6S^fNy~)k%MW=yU!8 z2?viako*?=1rmM*Um)hSeSw6-I;i|6sQgi=zT00Q>FmQ7Nc#En1rlE@Um^Oqze4!@ zP+AO1%YKE_YbswM_B(%tlz$OlA?_{s3hAFs`wHpT?)(br|K0rxski?@AlH50$_34H6E2zd_11_3sdW`#|aV?~wQ?`VPsDJ>MbjT=5-Z z?(y%C@qnjLn)L@nz3LB$y!{V|`(l4U?63a;v1i5)hmQJD53!#R z|9bs|gn#Z&hdyRvg#U|Qko?8)8^CI5dw)aH$-3VVe_#6z z3GW}jA^s5k1F>KG4}|Xq<;VPis4M>iF@MS*h`TpK<&Q(@M}Hvo&fhydWCX8Y z3S?viukT19w9s&tqj<~l<8 z;ZQn<31V&|6U3aEOpM@lMVp}N&oMEA*ZDkQg4oN<3^8Ad8KT~bnGw8xC72l^U&zb| zUT4<9%m`lZwUilR?@1_qpP3Q7p6M$yBz$C8Aokm_K=g;PFoM@}Z%PJopWysk`%l@Yui%$SuCypAoK72>XHR*1W1K>2&1{F|&0 zfBj{J_(zrv5)RgE5ch|(LBcVY4dUJ=C_Re}5)Yf8@|W2d!RxbLurY$yNeQz7 z+>rQP!VPiPUT#QuU54_XazpI-4OJ)31BrhF9*8D*v7bVlOu@gjV5&gsUwt#GMhm5OXtlA?CL5GJ@x?XYw+F*HfL~WdyHxJIl)m zUMF&sml3=^?+KLuikA_*e()<){3kCXc%9&Xs6IA6M({dAAwGycQ9efS`b=p)M)0~s z4L(Nj`Zxn9KbMaYyza7;4-!r-d=UT4;)8_8IzC45y2Jf^5PMEQ<LfP{aB0L0(9 z0*v7GrF8<3e7RZx5>MBl;;e!Y^Nj={`fUUu;q4*_^_L*TJU>B*dxN3kiGq;uO%;T= zw-QP>K=ro^LehCJRQ*yxNI0&9%5Q?wI|L!=Yo8z_9bJd2dm{)5zpqd}gAl|XP9cc< z1cV^&788P`GX)`t`*fhRl@KJodI&+{H(3Z`UKvzrU64vB{_D4iw_iPti5NVv9&L*lO=Dn3UX5>Kn4^mcJbI3I@U zzX%n7C=T)WTX9JGVUd93D_#jme27Xw{G%WNNzc|2ko4vx0ZG^HQ1!kN5O;(^>3FER zOemcv0dY?;lwS|k*8)}F12un|1f;x}3$=Hj1SGz1Nm;I!TB-+MxVNk`RB*g6dxgHE$EtoFkHucsd0&?*UZ(Q%Oj; zy^(~(E3*`YmWI;CQjqxZmV&q=N(y36yc8t9)1)Bot%i#CNJ0EPSqjq5+9Cxhudhi# z{QntB3ra)$qc06n=MUuV@<=4qU)XkHF)D!#VAoe_xgP6}I58*4yL(FlNhw7Jy$k)k3^5IN*NIPjWRNYOe zzOV9-_?J|G(5g_{5K7xZX-_B}3Z)aFbS{*xgwm}Fka(P^0EyQ{3XpudT>%pR#}y#y z=b8c}|Gk0Izo0aSB1BvaN~=I=BPi_vrTw6E43y4-(iMu3@}x}>k{)L&Lh{81sQe*C zi2E)mLel3$MM%E>sR+rhEJ~1ilTQiaP9Y^mh5!Zz1`Q=heO(FV&r^b!|6U1_p4pTk z`nZ)L`Hf#0A}*>730Em)i2v1;A^tN}hJ=f=GQ>T>P&!2!;{H-)NW66@L(;_}Wk~!U zQik~F9@M-KQ2IaAJU$hOJ#tW5R|R5^jS9qG9~FrCQBXP;D&L?2F?Rx#zeok*u1!$! z!zz$+`>F~g+}=UWXH$j5v#2V>d@U&7LKWhEUsZ^^(^VnvXjX-oJ6RRtjwMj>?W&OQ zJgy3H$33WdAE4&_gVMrkka*EhgOu-fYLM{tR)hFE94els2C=VL4Psxj8pJ(Q)FAF$ z2bJFgl|KWe@2WxUf2RiVFM~S7{gP1H6iNrGL+r~{hq$Lk9b)bzb%=WwK;_q{L)^I= z%0HnF3BT*=5dXechq#kX1EOC{15$sgXh6)j(15tdT?68eNDYYoEU0{w2E_b{Q2sm( zi2ZA!{GCwxga*Vv*EJyae$ar#8@ncimeGXRW2gx+&sh`Vo&ZgVzBo;Yz2%yacqWY1u6GcwIKOKM+;()5tQ!$rQNh3`N;>WK0piN zj&LoAdkeH6^>eEhB;WQy)z5&MH%ANNpH*5A|LlR%C!ywFgQ~xy1*r!gK;>UR`Cp;t z|Am^*rVVkAfHtI`AfgSiUtAkvzJfL+-gLDg;oztZu|E*XPll>1)`s}IK^qcJZBTP3 zLDfyuhPY=L)ckc&`R&?_4Eq@w7oPJ}GB7Y~(PadWSG?1Oq;GCLMurdu z1_o6P5F z7{Tj-Y>Xl9-)PLp5Y52A@XDAGykE-Agb}=su)+l5pUoza`s;!Tr2Knr0x5^NO&J-i z85kI1Oc}xZvu2nwg4bJ~H-)6j-=>iM5}z4FzqJ`8y@i=U;xE<=626IMka)|4ikCsf ztDx$ep!`lVNIXw8V`L}?`Ns_6ej#&+z24>!cbA(pGNgd^mzgs%Br-5Ch+9D1U1`C{ zPzl;EXu-&k%)r1PYzc8sxg{hY)I`<3k=>gL)(%;mIa zWC&(pV92*;WYA+|U^r~g$gl*op2vZaAsn=h-w_g@?;RoW!R-V|M;cC$`1WyvxVPE~ z;;+w6j12h<3=HAUjNo-o$DJYV4NezGJn6eIGGs9@Fr>La(%(fFNcg;Vf#er%SBO2* zP};(kks+3Wfg#it60e(G8NvG4Qa=6lU}VSx#giw5Zt{f0 z>qk#WdJXepWQYUBvlk?M1-%);`yO1p8NvJNs=Oig9`=T$6Mi2^I`i;>gkPu+#NCxX zkZ@k%!^ltr+REw+aaXM`Bg0|PdRkvbhI-KYI6p}Kkn?8*uWJtQhqNmi{2}4j>JQ0> zOZ_3?w--v^@`r@?cYj8PJ_ZJcqyR?nzQ&IMj0^<~3=9>4kaF~8AS7S>3xvcMQxK$_ z)d+(4%P|Pz&+;Hhysip@q>DE}jNtu?9Kn$IwGD>YR}u_~r~AQ>^vDsy$PmcDz|b55 zk-r)O30H?uM(}#F^`VRmIiT_-3?knZ28q9~VUY5|E1Z!bih+S)e>g;)R0JeG+9M$8 z;0=`T8wt_3DUy*P6SUqg3Zkws3Znm76vW?#(GYtVMMKhsKnx>869WUo`WQwAPX-1C zqgY0UGzJESnpjA_ejE!)7jkhB+9VEAu6V^UGPpA^Fr>yo>{|=vi^oI!7atEPXU@e# z;{O_y|2Q5}p1h8Sg!`9xNPpu;JS3lsConREf%cyyK+3rb36ONelL+yjYa%0qJ*XT? zWCZU+zLf|G7u_UA23L@H5=8t#5+uDFCo?kmfcDQOL&EoFG9v?ML$yl^B>mhJLXBH#FLQwsb1<~)F&BzeK%)l@|8)E*K zJcz%N@*&~9H6IeL@&%A`RHuLuykF6|0FwR+q5N3|knlTE07kJiXi1tL=hyuGm0SYt%K4lp!B68NWS<}1gVGhiy0Z57#J8biy`r|rWi7Q|E3t? zZg~YRWDa1YPrHl-I3=9kxN+IzeUk0gfv&$gz+sYv6?td91 z9^A_z=1eJvgxlG2h(5&%Mh4Kj+T038@Ou4C6%czqRzT!+D6el1DYZ7lbRv!xz!8_2aOg8KcxlYk4-HQeeA7} z@-4m<;@(@W5O+zoLClM5gQSZEZH(akOSjq}>4>i#qTiw&5^ocr^vQNeJ;c-jNzXhT zkn%&h1Cq|Qp?r%DNcrK=0jW|gT{on? z=-mU!Km9$B@@0Mx#NPc-`cV(W9M)b)e_F2>Qtk%#LdvVTy^wnOTQ4MheEJ~eNNXQN z-Sa+(`G)-v_c``M>f=%)DOcA_W@IR3U|?{X0;#`u zKxvDqj0|NA3=BJ_Lh5_{X^ae$85kJWOoQ+prbGC9r!z84V_;wioWaO2fq{YH#SDmi zwGJ@Cj zOV5Mo^O?s8o=2T94^m!jnFonC#`%m4{-E;@=0nQM*7=O!b2^UBhnT~&07APhfT(L& z0MUP80mMGpg%I`W3nB5kZXu*Ubz>nU-8_NPvWp=6Feu%>2;%<}iy-Of`yxnxg?%xk z{M1|w$#1obA>rEvg~@ z%=cOk$$t~pGcsr}GBCVd4~b{7jgWF6Z6l<7*uN1{jz8H5DaQ;pLDGBpCP+IpaTBEd zTe}I8AE$1DC zAo=p<4oLX?+5rh)_nnY@mADfUK1+5&((S9A5O*l=g4kcQ3(}rHvkQ_>qjy8>6{e+4e?}Nyv?1S{L zrtX8Ze>X$<=k`JT^=2Q$ewqCczVUuYd?xRQwBtALhlG>H0Z6`^et?l-Iq2M)1CV~F z|3L`-Z9AGeP}#w|RKLG*PVgS1!X9%E$K06H(` z7)1a4;}G*MABTk3_v4UufZ+*7hFJ^@3FN0%Sby<^{<7$MXx2d?<7g zQa+hqgp?EE7a{$=s*8|z_eLmv{~{!x@?L_Jqb8Ri<6w@LAoc}cg5<}immu*Jdl^#B zbX|tzr{$L+>jLgvhPYeu3Z#6Ax&lcD3$H-zU48{p?%lfr$?rK=A@WUEA^EA}D#V?O zu0q1`C{+B*Rfs)&*C6T1`5MIhP1hjh*UxK^_)NJDao@b_ka#?O9TNT~Hz4(oKa`$% z15%DXzQM@A1UjGNCL=>X=p2<>kaGI+El7E2c^i@rrrc&^SkJ(~z;p)^4x8>k>OZZ! zkoIrZT}b({_bwwtF{oW}4>F$9dk>1gNN-u`eZyrJ1WBM2p&J!O)%Gu?Q zA?=3)k0J5<>@g$5N(KgoACDOsPBStvEP4XT&w0-v<4?lRA?0K5b4Y!}@`91!7y|>t z+!v5=Pk9M(&-s^-^8Ln3Nd5HaB_ut{y@I%3=M|(qYWWIM{^!4fsPBFSao^NekaBJH zD@Z!L4yFISf|PHnuOaSle+>zr1yK6oYe+aLy@9wx>kT8rUj_yS<2Q^9;YCXNW)2KSRpN z{Lhf^ZG*~x{0s>{@h=c{zF#2eCiDx$oYF6l`eX7JNV&TD3nZMMeSwrqOkW}Oi2GMa zKAZa$Qr>U>3Mmhte}%NCxW6$n#4<53=zfFP)BOVyf0KVe#yuANfQT>o0ST8iQ2yp0 zknrFA0}@V0en85DD?cFPUV=X%`o(@i_))WB~yM98# ztshFy{0XsV@lS|WAZOZeD(c;g#VOZ5cRvD z^zmO1`>yr%$7ZSd)e9Q3nzWg7={_X!D>Ho?Wy4o-(UBJi$UQgBqA?l-8A^xakg_zR|<*#LB0Ror!^ifq`KuRD2yf z#JvaEA?|v`4sjrS3OyG5^Ts#nUmOK!3Zak3iPv&8Q zjDPb$+;I~s{|72B$qP~E1f{ciA?l{^Lfo;PmkGQc_A)OMcwP1lsQgP_hAm*LqV*9J-@Aek|2>BCpF{P%g_`pfD$XRt1fIX(5Q5~F zcp-@YX9_{W>6#EEyq^g{?B^GT@MVM{;qEF7ac71w#D5*a5ckg(hSDF37g z#N4wYkn;1g2qc|-fyxVtLdpwKQ6}&{2Uk%h@HkkkD8#*eq7eHhi$e1EbWwj46x^dt$0yDm#W+<#pH62AAL;!h6#?OAO9sG=|V^f;(kpjNc_Y|F@g7I^hiPUEr-fq zl!C+?i!{VO8EHtlWG@ZT7XjsWNJGqBC=Ch!9nwtT^$l00nHYLN<8d-f;Qshw87A;N zqK_;ScwT(7EE9NKSXmAdJ~QPY`G2Jx#J&6Fn8529F3B;0=Px_Vo#|8#GkDSkZ|0p z0Ey>&Q2K`g#6BTK2yLVYQ6HoTsaKm6A?aqlBE-CFQ2A$yknj{!f|M(kN|1Q1R)WO; zMkR>$ZS6(;b! zOPC78yb%#|U=0AX{ z`vv72szK6)w;IIUBsEBQG^jz+-*PpGJ8r2#()ll_ID^+2*Z6L?)lo;oDI z9D>R-Ye3@5SOel;2Ms3hdXQudCh&Tk(;ATY7Sn{-Z=(r`mncn0z16M>(KiE1@79F4 z=bk1+-#<+za6PJ`1qqK}El7M7Xfc7;OKj4Dgb%+qMBYLh5)Pr-ka8|x8&a+=fXbiI zhO}Q_YD2t~cPPI=2NJ&%bRh27qyuS(-Oz!U&#Md7rwg&yT^Hi76kUip z6Llf+z6&b;L>Ch7f_jknu+W2;@2>}`j|%l5{#*@}zoiGU_oE&p9>nz_<-0qS&d_H9 z&ntIA>FxRu_dL~y_>0v55-$=^TGarOUW^PN_B$Cs;x*C$VsDB8#Qezykoskd0VLcm z7(mLwKT!27hLCvVH-wm{YY4H=)({dt0frFwwi+^l_vdYe%HJ}C!1L7)jUeHvVhqt2Xbkb+L}Q3MHyT6yf5{kP4uc6qUd{v(u69s< zf(a9NU0Q<)Bs_MSK-3>Ifw<#|38Xw_G=;QhrA#4wOH)Wa5@ZT#Z-kpd%7tmB5O>Wo zg}CduDa60*W)OFqn?d5a$_%1zp&29|&zV8&`(g%3KZ52=;Qe>n=8*8VHHWxA(i{>$ zmF7&~dGZP7OyK#atL9ALbwe^1kZ{kifP{O61;pLmQ2r{Y{9X%)eP=Bo?tEnd$+udT z5bNb$_A>0OH&myS!2^)wze%L_Fv$ln}r_mM?E(>iT?%81r zsi&^lLfrEPD$j2R2_H2(h<#>u5c`7dAo;P`4if%rq3Vv?LGtT$J4n1S*h9=yw}+$` zFMCKhhucHU%d&^)Z?}iWuRSC^p0kIP>+kI$?p1bx(9RAJdy^d?>8jTO(oR_B0IAnc zIY7#@M-GsDsN%>3UUwDj2(kZyBgEf#9U<=e0u>i`f|#S?1X1VV1S!8mogm>E?F6yE z(TNGX-)*52q@G#g#01{Ay3PrbuMayhFZ2RZknq%Wf!Jf| z0%^awxj@3--vyF>Q=$Au7l^sjq3Y*D`D>v1wm|uNq5PvRkoxqbnr5HoHRd_aj$Gc_r-zq21je?TTVIh?T zn85291Kc6>Hg`yRknw=ze^(DkczSt2+CK#zkap884<_)v4PKs1;B}3MJt6LM@`8km zj~669lDr`0MurzeKF14^e#@ZZQ@kMIKEn&*-mOr2j~67}9fq274XXZ*7bG1#@Phb< z*&Cux*&EV6F!P4gd%50_c$()8iNEDgb=$om_MC$9FM315`-wLs-~RT7rgkTW|a!_6Y_++@l@FA^P71Lei^x5F|W60@G=)RLdqp@T{;!8a^6QguNWOa+4$1fL z!y)C__i#vh7L0(X(}B{45lrCy#AZ;wQv}33_XvnTLLwmUFN|OUulsF@U;?k#eH6h2 zUN>zW2@#(k38}aKMnd#EL_uiZD2O>xQ4n{PM=^oV9jJ|h)PEDBAm!d2sJgdN5dU*U zL;Nij4e4JvL;2a!5ObzPGlADf&WeWk=SDOnU*C;}g!_|dNIrcBm1m2AxQ9Ci;vNYo z-!ulI&nX5HPM$Fk`;ucI=5)tE!h32AB)oS+^}ULL#K-p-Ncix^Ldp?^SV+BZ9t+VI z1{JS~h1fe8D!w5W;?HZbkn-SJEF^s~#X-zdjf03=#6iSEpyK6F@h&KTSsbLC+ZhLO z@1ZzIxp)RD|0WJ%&;K|`dg70Vgo8#r#C@hvIyxTWpT>BIIn$y1h4B!5+v6eSz=e2- z`Jdt;@gtM~aj$g(B!Bxs`3(t>c%Ga9F>iSSq#oFq0I_!~RQz@V#D7l{AmPK22%%M> zv=fw$htf4rdM1?K2Bj}U=?_qvHwofCtt2M!zJ%Z;h`s$u5c{@5#cw1*;$0+}3A}Gy z4@%oWX|H66d<2v(g3>)udKr{H0Htq1^?gZ(*vFItDQ`4VAoeDvK+YB|uSf$0f|q&3`o2?W zPcJec_OoU}(vMIk#N8U15c@5lv>jC5B@?1PDiac}=}>-SCdA&pOh~vb%!K62<52l? zQ2nr{c6OtcQvLNOKXF=M730aWz){+I0@5_Riw>JyokH=XMb9u5M{uR!K*sBkv zouJ~O*${IJq2hJf5OXGGL;Srx8{*$9*%1G}%7(Nve`Q1b{WlvD56n3bbJ%kr_K4&_ z+9~Qekobzrfw(6*2U1>VvJIW^3@zj`uLRtX&*}FLdZ(|^XEgtRX-nM zzI{HVAK{Y^ad%lhBs}Iq%=#s|z6h-Up?x6hO+~S5W<*q3U@HA@&LuLfoZY2yuT%AtZk5 z3L*B+E`*rBun-deOA8_XT?^&!DukGSs1V}c(@^yvpz6LrX~rUmxqL;Ca#*_v60fmE z5PvrmLBeeTRQz}m#Qs-B5O;nkg1CdL7}6f%D~7not{7s!TQMYD{fn6x7#SECF0nB% zl&~-`oCIC+1X`cO!oVQG%D~XW%)r3K#=vl$m4RU|D+7Zb69ahN31}+~=zgy~%nS^t z85kJ)nHd<;Sr`}s*dXWX?_q(QOZ|?CfuVzqfq{jQf#De|1H)}LkWL1M3|0vJ8bX1| zP(}uZI%dc@(_jH4VhS4r!vv5+85kHknHU(hf$pedVPIIx$iUFc%)r3M%)oG+fq`Kn zGXq088w0~JW`yQw76yh+1_lNNsMt(a28KqcKc%4VDS*;TL4JYCtpr`*1~sOZk%3_v zR1HXIIVilK@{1W67^Z^+85kJc7#SE2K*d2qo1k`r*p93W4E<0)#DUf*voV0jtU>!* zK=Pn{ZLS~&6eqJVFz7(T=>`)6!v|&thR0B|O_0p}0@_E#202%(4Ql=bHU@?Rj11s4 zQUXvtRcs94I>w)kfq{vIfkBy>f#E0<149FfuTl0_}%mWnj={W?=XXVnglY zWMW|OWMp92&&I&;5*i1cNM>g;Gcc&JFfh0?GcfF9VPN>l%)qdVm4V?Y0|UcskQkC> zJWw-1LhXzU4F5n31_lNd76yh-%nS@OSr`~jAejx4p3KU?V8Ft_FcE4uNbCax1H(tq zem&5ggiH(!ADI{!oLLzdW`ZO^_n|RC&J*)xV_*Lje;5!)_)91~pa&hJTC<46~RR82+*{FrDaLpu`#!(pg6NFNASvN3??(6m`0XXu|}V_*nkWnef6RX2x?fnhb2EyBpa5XQp5 zpuxt#@Q#H6Ja@jIiGd-VnE|}t!I+hS!4%{+(B3#k2Jjwe(7xl>EDQ_>Ss1`;`#4w_ z7$TuzHHDFZp`4L{;T0nT!vtmqhP%uR4AU4H7!;Wq7<{1N*vQ7fa0=@8XsFmf76yi7 zMh1pNW(M$nTF~8=l8g)tGeP0T#J~^(^>aNF14A{`?KfE&7+jbb7;@Mc7zEiE7-E?j z7?{`?82F%OPKVl2#l*lM2a;!HVCZCHU@(Eo%QG@C)Uq-#{AFZdU}Ixo;Dp*Shmiq1 z7M~B*KM@o*tPBi0SQ!|q*%%mFSQ!|snHd3<+!u;JHI}76t}?CI*JRpmnUEy`?M+43^9c47Z^6-(zNA=z_ZOC1@`u zD+5CzD+7ZaD335Qfal*p#u_m)Ft~v76cYmjHxmQHE=C3hUls<2I3@;$^^6P*JDC|6 z0+<*WtXUZtcCj&l_h;6D;u}=|L;VJ|5w*ohCEQY&dR{R4Ra_|j+dE%!5vh-K;6g4%)syfYK}5! z-#*m+GoW^W*2?=r#fqU~p#4M}Sr`~Hp>Cea%D~{n!oX0@#K16#iGd-Nk%1urYJLSP z1H*h)2GDU93@mI63|3IPpw3~aVPRnS$jSiTEAkH%7f^jOnHa$PLiwTY_hn*W_zq=* z^sWPyN1*#Vpl))6y5%|x1H)Zb1_m!S28J{?2Jl`VWflg8-E0gDS6Cot*uI6D)5FTZ zP{Rs2pH!8ZfnhHj14A{)aL_(wCI$v0s9RPuGcZ&^*>jAHB1Z)?ohKq_W@V1FfcT+F)+w6GBE6bs=dI(z%YZAfgy{9fx(%L zfnh6XpEx4}Ln#Xb!*r-#kbAjV85qo=ahV7WH;}k8lsy}2-fA`m21zyshGaGd@E&eK zP?-$%|9@r%25)8t263o4@k|U1pOEaRW`vwe+QP)ZAi&JPa2#X-6n|%CU?_lw0Z51$ zY9{Esh*qfGr&$;n8dw+@%%E;kXJue$f$EW9V_?u_VqjRq%)sy;WB>yLgAfY?0}m?$ zgC^8HAYstH-m_3Wpu3417#SFZm>3vVGBYr2V`gB8gPMJZ6>%hXmkj%`$Aj-zTUMa%q24)rphDXpa zVP<7uSP1ol161q`l&{0az`(}Lz~BH4v)@b%46m3O7?y#;9BMYmTsI~Lh7F7i3qiHU(hmW_eo2NMIsJXXm0wy#0$c2)+4J|+f+ekKNni>wR` z_RI_nE0`G=RM{99rZ6xt)PwRY)ShQd3=GQ{85ou`GBB)QWMEjy$iVOm6tpVbGkug6f~^1u`n<^hq5hM7{Gfxo`4jC_UJix{f06qf*v@Zyx26V66 z15kLfGB9ie^(&bnch@;W^?}r^2Bkw#z65cQa2FE;Llo591SSTCUKR$1n~V$$-AH;P z7#J9)LF4rd)Xz6T{TLPo1}hQpw^XJKGC%*?=WhK+#%wBKY$iVP|fq_Aei2=MObULUF0!rV^3=Ahh z{(#!G6KX%muP`hNH7}EqfnfoZZOFpFP|3=`u%DTMVGk1nLm(Ri!%5ItFKi49^Feo@ zLp2`(wT;;r80LZYYp^gdT!h+l1!@jR*;kMmQ2+g4gxvjLq!y%J0m+TO z7#J9Am>3v}7#SFP7#SFJ85tP-Sr`}$Ss57qFf%aRV_;xV1ho;E85q8S(ik)3EcXQr z3=FP}3=9WBZClV??92=dxuCW;D6fOU3F^-6Yzz#pQ2XwI+O|+}kUO?R!yU9|vj!x< zz`$^lm4QK(i2=M%Zz(eaLo+J_!)rzc1|6tcs4_7171VA5_35E<&%mM(;uQk}gD4XN zLk1HA!vUzB9w7HY(+mfcwqs*pkOK9qp=y|*;*n4~9+c-97#O~S#|tbJkOzey0|Nsq)DJaKI~y4p82DHi7#6THFkE3{U~plB+&$UGz`!8I#K7=| zg@NHZRF5>&ZfQ2iJ#x#L7#LQ7%3>A`85tP7pz#2@*YgsnOlDfXWsY28ORt^Bq_j zz~=%SV`X6Y2sQUM69dCkDEkg019(3H$ev(E28JJ?x(XT(Q&<=n-ZL;T9EYZlW1#*u z8v{cYGXp~u8w0~lW(Ed(P+J=6t_~i(xt`Wy=b!%|iT24|?ckIW1V%xnw{n~>}jg{l>0WME(i?N8j*)?(3u@kaCI;}H zO^}+6P&ZuyjU_|n-B=hHUW3MMm>3w^m>C%QKx0(Uv~(58j^`{43|pBQz~`ievN14p zvoJ9H1@&7Q85nFB85oS&7#L!pW(pzc69rie#c8Yz3~g)-3w>lhH)M=j6iy3urM%uU}Ruu z1#v)b1+}jj7{GfiKtke-3=AbuJ6b_wC=3h?mW&MGJ=7Z+7#QN&7#Q|};sjLRFflOf z0PST4^*cf33o`@5dQiS(U|=W*l{29H&dR_Lz|6p~gN1?N0xJW<6R4Z+F)=XwW@KO} zVqjnpgZkSB)Lvj@VE6{LALJf)HUg_t zjA08C1H(yX28NG}3=9jQ`j>*j4>Z=w$iQ%pnSsHCm4RV5GXuj5W(I}`sG1v4H6TL@ znHU%zgBT193|paTQjVE{frpua!3r9NiHr;k$3f*A69Yp4R80%W-%vk*w4Y^SU~pt+ zV2A|eJyr&WOHjMkF)%QgurM(EU}0d;VuIYia)^zA!51`M0-6tDW&ocNm&OdaV-sYS z2sFHU*%%nkGBPkoFflOPXJueu0fisvTnI)624`jl23KYVhIPyg42Dp5W-&4_2!P5| zW(I~=pz#e*p9Yk_nHd;D7#SG8Lfw7>G-e7717=1Bh9k@j3@L033{Idl#K^#~orQs6 zCumF>s^%A{?FDie0|Ubi1_lOsW(I~5HU@@VW(I}>&@hky^>0DrHjE4m#i05GR1Sg0 z!dV#@&V$-sObiU!Yzz!>EDQ`~j0_C(*%%lWvN14tL&Hf1lrI<{_ltn6x&!qSi2WQS z2O0+f)hnQK2$X)A85lG{^F^SxA~OR+9y0@YZ-@tId>`s=R%QljJyK7Rwm2JPQgW`*3d0^%Ej@(rkc1`W$7W(EcsCI$vK zRtAO!kOCyk0qPS$)fI!8&&L3{+f)x~_e~ZChC)y~n3aK{6*QLwnppS$)i0Mv#A%~62H zBS7O7P;roYVMYdqhoF7=ptTH0adVQ5fngT|1H%f?JO?ua!$ejFhN+AU3|gSET&R0M z`a$>-GXujUBsYM>3PJTgGXp~@)NdfMS{4QdDHaBXI#9g`HA9+-fnfra&CkTZPzzOm z8Y-60%)s!Dk%8eS$nBu9Ly$oX3=F$KbBdsFf~sp`Vql0xa>Gkz1_lwRS>G8M7;dmK zFl4eZFf4iGkq?C~QD^fr)`(J~IP@A2fYzf!dn}vWtO%A&-#( zeEz{9CI*J+S9F!(~%ia_0$0~!;By5l9NJZ52FxXsMK;0YSjVPatT z0jhV{7#Lo#GB9LA)q$K90rD@X>|kSHSi;D_a2HgrK+Uv-y6XuO1H&{X1_pMJJg8n` zW&p3>0qOt6$iTn>bqk1Z0~*7I>Id;b*qDWZfsu)UA(NGX;WDU=0xIuV7#LQvGB9XC z!waOYk%@t!hlPQ`2O7>GF%Z7R#K2(A%)qdpm4P9em4Tszm4V?q69Ypo)P41!aZ=D+ z5Ca3lGEkeGfq~%*RPGTA1H&??9p^x2WP-*h86o!rO<-VPn8C!r@DS8D1I?d7!{q{K z+yzu0K>cL_YO{mJgBTeYctP_lP<2aK7#LPCFfeRnWnef0nu}#(U^vFez`)4Jzz`1V zE3q&zWP{FkK=RK7sNNVJ>L=iIstYk&S`D18SBW0|UbX(3~Hrzs$tIV8X`0@B!2w z2l*2;Pshr@umKuRzo4`dXiN=icRLFMLl`3i!&)W=hCV_~Vy@`ndd=}zOHU@@r76t}x(7C^i3=G#mW9gu| zT?Ph*RjdpQa-ebeA-#K6!EbvMYqgCGJlUW()fs1TUC26c}%BLhPK79?{)=ewpt#qTpQFnj}z3q$qYV`E@o2c>Zq28IKm z^&Ox#2`dA`FJ=Y?3#b~<`G~8aY#$Z|hW(&+5Gw=2JE$GoL1QVPFb9qKg60UJeg>WI zs|7k!mW6>KnvH>BG1zAe3}v8k1<-smXbu6CPna1P8kiUu{zKjPmYD&(N3esLfngC; zObu!#$cT1k$Q@>$pnL{(gAx-1LnUY)8`LgiWB{*?odQa0ObiT((69_=V_-;SVqnY72nO{dq4x4X>8orE49y_B7#SFRSQ!{%Ky#l^ zxt*Z-3s9L0DrZ?47(791X`u0Ro`Hek4l@J8B?bnDD^U0BVPF8C{Q>gRT^0t0Hc&qq zH1^NPz_6Evf#DyhTxVrq*u=uXpb8EDTZ{}0?Vz?C)ZZYzd!cflSr{1Zfaca285km1 z85q(T85k}=<-V{mFw{fYM_Cvc+CgnYMh1pItPBi0q2gjtw}Q;9Vq{>r$HKsn#Kypo z09r2r8j}RgWrD^-KoSB!BTA`Vuke{ZYs!@_(l9;2J z!l0^wO;{nbBsEu|I5j6Vxg-^@qGDuKMfo|Yn#Bq^sb#4-3aT1l8f-^tQ6@+{GcQ}A zBws;QBP|o8kU>??C`}}VRDHo)Y2su3@br5!DMQRRM5X1o6UR;ovoC*>GGr&S6iAf-VlEfq!HwUbu zBrz!mlwML4O7qh4lS_+JQxsA%6La#x!H+Hm)?1oamRX!xlA5BBlbHwhI;sd*5xNp& zelde;u>vd=mE~uG+*%AVOhXlBy(R;KU98Dq0M19n42A{__V)G+jtY*>p&_mejtb76 zLC&GRZa%IN42}vQ0rw!sFc2N&>F3Vis1V}m;{xJ_`uaGAhA=pS3YomT)EtHUyqrpf z%ru3}l46DU^31%H{BniNVui%ylFYJH21hWZ5Fb#K4@yZ^Ac4}v9EISLqRhN>2FH{X zg{1uaY;fc|reu{Cm%wwcLSjitQD#zUNh*V5N?BrFa;id3W?8C2QEGZ-ex5=>eokgd zYF=tFD8HAKfKAKE0XZukG_ClR*rQIpv9!#R|m*sfpPL=N1=$l3#H~YHEo>QDR59D8LLZ&n(GMNL0v6Emz3TOVwj=EGS6LOHnAvNL5JA&nrpID=Ahe z%>&iaX*r1{3Pq`9nW^O<)4(cnG7FOO6N^%y+EPIc4XCD)e1&9~G}u^Joeol)1M+-H zz7>OGQDRbNvVwb2VoIulA%i0jo~l2}v%$!ehBO;jjIOizVm=gbmNL6eqQR9vDE zpOc@MlA6Ncl$sh}pio+nk_f7ool?^?A<>ebrcjh$uE*e%nvUt{mlhR)>X?H3;!IE@h`}kpq$EFA!6!AX1jf!! zgEr~(7@Ud{GjnoMVYGr%W*(@XEQSks=B0p|Q~5;yIgHus{d2uQ@*pbH|C_u`& zVk`=Z^2-sj;1(LF(tdAoD;8 zA5k_r=ND9h!;O>z&pE#|Cq)62=D_Wb#FA975yh$C212nyZem_ydTNoLf@?)4sL7zm zfY6banU|sf%jK|)p~v71Ew`bK_aJcRh{3s}D2Kthw5T}0NFe}LB0%{;`K2JU8JtT? z6u>1AnB|k1mkMU!^l)Wz4#c@BsY#{j&^`;ObT7?QD9OxCWpIY5$Oro=4-_fcsg(+; z$r@*fH62%fl3)z$?oDA#NZNNS_H{}8pWx}#hO+OE{P@asi2xHH?hQu z!6h}hC^fMd;VPy(u*rgL0$Tz$2%#@IBQ-f&At}Ei6{~DcW^y*jSy(0WbCdFMYE8{6DayoZ zD5#OBkd~R6lY-4uPY?4KZDVg~SkhFnK9@0d` z;sx|>6{dSodsQ%bP+f&I>Y-3jl$w?bsvuK~L9MW~%yd}Bf%f!}H4;{w4=JZ$eFQ{1 z6tfws$KV1{T~L%?mYI?Y>gALu6y@jVf?7t&nQ58H3eeuMLPlnBNj@lr!8JkpDaoMr zC0I*dVs0u(vP2=?oWUi(L?PY+L=`KTgL+6Q3Kk45*s3apWKdO>nxcn88dPzEhKfMd z7byKf%>Z#hX*ab9(*Ptnm~P0B7-+c571}p-RY2;Sx+*~WrLGFlj;L#h2ZL*JMn0H; zH6HxHO#_fHOaxR=f(C8M^NUjSP}F9pR-y_Nr-Itb$*HKKAdTQ59o*7-46fj&mIAcx zrx0IUT2PQ*R00!^Ps}OENK8rvHJ!6lD~sXcX{C9|pf;rfiYUmM=S9YH-34<7h{+mF4y4p)n< zHIL0ua8Q;PB^JO8PE3x+@IA=m3Q3g;@v!iQDTYgcj6oMn&Pa?0HBVBDU@~briNzTT z@zC4>5AvME%KXw2NCO#^XrYY^n6A9|(%jUd%w&`h&CAcz1qBGG9}=IEnV4LZS(2HY zn1iAS(gIgV0<{aFZFFb=L1hqqCI;6$@X#m7?!?Tz)FMy<0*ipVDo|N)vBuz%n}9UULUCY1(gS7&^)lG^b`~Via=e|)Z*mCf>clk2CNaG0-^=v7bL?#E+|O_ zk5V91!p%y|s|5KKWLO5MRSO#OfhAo%1%;4&1xPnEBUJ&VOYo>+X0ZZnkPe(6bwGt_ zaj}A%p&m$EdTNORqUr^eyIAx?8w{{v>0-DUMnszd*9&UgfLl??(2fvNIS)727;G+D zu)$7*El&lc@I{Da7MFl(1yF$w z4kuWt4(ZD2F}Qj9xH7n9=B0oM1^)t2z9|NAGK(`nBZ>Lo(O3o5Vm%B&Jq9;$UhsvC zsUjLpZlLi>aH?TIFhQ*^NQ%{CaLX@BPE{x^P6c}eY$t@{i|%Meuz(IP|<2X%0e3qod$q z$Gj478v^QJQ1z6AJo*U|$U%f6h?@i%z|2nr*My+y86?fnf)S(+O&esu6;$ei8h42b z$i4$B2el~)NFz_=lxJinXDH-?hME&Wb2N}S6VQAfl5@bt6QmAB5`_l|hD=F*0jRP9 zxd-O4(gLK~p(r&q8(ISyGI)T-W)Zy7y!6DP%)~qe3-CmIa(-?>DQGg?11keECIcRO z!6pG6d-2RGPAw{7@C1#y!Yg1y2Jh5L*zhzmyBN$#0) z;F4dS#{g!5=LNv5AW%C5A{bi0-~(#ofhQMKQy|3>hDb4k57I;@v=a$xkb&kSk)%Ma z!n{mSZ$B?x0k2#hgHL{93TS!>oEyNL(&E%26p_rlbWl@22RztUo|svp$KV^EUtGfA zn^=?$%IitcISnu$l(kSwm_!BeI5B*96QT{I3|f|8Q2?5RiBHWd$t+4$02OQC*<=P- z3pK4MKNo4JL$w$t1DT?WPf0CF%*;tmK@$colF2LvO_DMArj{fcG5BWYW#*RVD&(Z* zrI%!Y%7xs-l4MYO8RTLs2H(tL@Kix+3fK{#)XU(T4-Q$BX<-K6{L7Gzc3CS4xz@;1r#h1d3!(0Kxj2AYq)20ZA$(rRL<9gKK3h zdceIk@H8Q4Kr694u~Gq?QIM_31tnB)5`|b)lCKaCsqPW{lKcV&Kj^v+KSy6z2EWu| z(7Xj=2-zzA*9)U#Fq z$%4l}^cei|6+lH1bZHTU5AqpE0%Rj-JQ|j#{PGoY^NUiEitu8v28bZI8I2@>G;)tn zl?-bnBP)cpk5iEZL2ctqWC29G7)cehNnDKF_(fO-lSPPt8^TEXQAX7f%0LYVWL2Q5 z0u-!hVklgA8x~0v-h4$8LvFbu3Bwz$NMhg?9TFe4sfr|l+)9NA=jE4R4qkxb6gvNe z9N&mlu9 zkUdZ_us0$6{5h|zoqs@xr@tSAKX@_)+KBPb%ZaZ9jp8R}gK|_}I%pIpGY_$p1~e_n;16141sTUr zfy|~rgN?zzATC>^|Ft{5s* zY{d`&T36wRSegXpgEA~=EGZxnVhOYb0IJx)Q#vJ(xkzvoK|l?7G=?Dnv@8KsQh|%- zWXK$|LVg~sc7v67NTmiy4``JfXp9ED@C97jA+2HwNG$>-8U>ImK&xAlvq1*JOhSr9 zNOKFO9PA(x)Pr1|lvtdZtPq}&T9m5b2wEkQUyur!JY|3x3sMGanBY*Ek)H>e1Awe= z0WTs0X~O1UM2!@HrYR=}9P8LLfl3T`rALB3a0MQa8DEl|VZ{)TpOaaPSRoUTUsO_> zUYc5*3hyU@#+N}0VnXwBQj3cjVBC0cJXL@PJySu0qHr0QTS04cFa*I9+%Pk8Kpg>W zMG0IRHc8Oh$Kn#W5_nyWO)Xp%XyzF_t_~Z{12qp}E`@e0Va@`_5^VVuwA-ASS5R64 zo|Fa~S*(zlQ=*+_21?KAphi5nx&!f&Gct2hpi2*n^`MF~zyr}4sW}CDTu>p<3Yp z1Bx>9O27#yI}bFD3R}H~l`e5V%244UU3O{J_4L8GmBB@pBSK8L1Rj=mB&G;pqW{Pq|$WIl6VE^>P%fw zx8ET>59GD{qI5lmAjrx}8Y?+JC%*_3rwX9u1jP)&iDjt@ zuzc%?!B=q3&r8e6OfG>ajEAX!E&c{+fUJ9lu76f=im$X{Kv{I90B+*AKvvbG$^;;m zW}xXok^z^ss>Nsu;(cMW>fWi98ldG*P@_TXdO=riKOKh!PubT z8iru#h8S=gS|PI-TzoVAs#dwkIYs`&d)DO$;<<QtlyCcS~pOZ37UCBtY?B&kx+9W zAqHy8Lc;)TEmRWH2rGz(t=NRP5IO(}TcH3|3l#;emB}wxz~~Y}Ri%~Y=P1TMXAN5Ify+e z@!&oxR4Tt5YAo`87*P7dlIFm<8oB}lxu1sU_CO59r4CfN!h1USm4Xrk)M2L0E>#!yv$_Krirq|oKoMy&x~8CTFmOr4}WDvPvan zOwdXpsVFlw4X11wSUISO0&isiEr$e;vx9>OwCp&(xU#q;HP;Gi0;*F%3eemEn)4{l zODs#w%mH}`oG?MkilK{!tAZkDpE0BQ%&|1gb#0v0q7(^}=w2wO^ zAG%Elc}o{W9yI(1mIf_AEG|t_$W6^Fg}ENta*(%EDYKuV?K}lsn zszM^Dd8beeZe@cT$szf${blfA2Zw2XkpkFV3W(5ySO(oe1FBwN4g<}~6+srAK~yt@ zfJayqkXDkygdnpo&^f@|{FGFf1a$WVq@2twfflQ9S)2s}Oa&;zfJcErnS@Y90Mk^S z0iMPIB^^*9pa5#bfrAcK;ecB#;8qei2s1$2>+*9_L9H5eGs;2fAF@CLv{x=q0km%t zbG@zJb{A)*VAgegR~U9f$#5=>qCCgHi@~ zg$Ja0#t;IE_{=7t>UrxaxaOs!40K`&~&~8dlTSx)Cy%RcO8eWuG0NP6p z3QEWvv>pSp7+7s2G{;85GG}CdsRFEy&j5`rfd;yfM)?x+6kt2^Kt&5|Uk+p^jzWGx zYMvff0Awjka!!76Drh@uQfeA#8W|)BDnOC;SA%T>?fgvw?FxXWE^s;r?<7oxt(4JI z@Jv&v%rE5vI|^Kuf|ssA$F@Pq0=$_V$x%8WV=5KOGjnpdl2R2?it-BzAOm->adOa@ zkscRfR2{?zxez9wl3ARb2Jq4G1kk1v$6G3wa`QSNK@FV~@ z=YiW;3MHVe?=WYB#1lc?IYNW(`DxHyks>Lw90;8t>qN z<`mdg9k>*vhGvKd4K*^vd!*(RFvNS6<`yWF*$q?`F%@7}uT2!2$XT=Z?DqcYoF~z01xrs%Upo$LHW_D2Y zr=}pZl;r1wMo@}DB9M3i?ZdZXh!09E0XYUTTFww3lvo#zT6=&Y;a- zL7@F&ph}hjDw>#+17pHN7E(IEJFMWd5Fn!uAQy#zTEL*mR?x=Kcxa6bt%BphB?`E3 zv|@+{<#2_>B2ep`AyL6f0lf7|Ml5N{aGJbQIDRtQ6AobJBDaG8C*7GV)7Ob959k6|6wL;mkxG zg)9Xtg{;z?%+wMcg=_^Y@F6}r3ONc^3OSj%i8>0o3RVianc1m23V8}v3VHcusi0lj zItuv;Rtou`?4_enpkSp?kXVqYqfn?|rBGO!nv|NXqfn$^rBIZgo0_kqP^@63P@I`s zRFtTrP@-U^P?DIJp0A@&s$iu6UAds6P^Ms|P?niol3%2wP_AI5P@a)loSj;!qfnt> zrBG3nSgE5>sbHm0nV6TInyRBvrC_B{Rhm=Ekf@ND3_9y1Q6V|AD7iE@Ehn{tAyFZf zAyFZ{D6tGggZAYxBr23-=A?kQrMWqYr6mkdZ8Wji-X2nl1lOzl1g)OQcD<;6_Qg^GIMeg z8Iluo7?QD^F~9;^VT)Y`Y%W$k;IRShnm}h2V3z@pZ(=nLyx(vOHDxt zfO_H>f(401C7IwA3<#-g2Bf45Uvb3%U#h{93_cJ5S)jB8iC2(V3_9B@IVXo9Ij1N& zqqvA6Ij@W%IX@>Or3gfUd(J5!R(>9sECSaXEQvXp$)M$7rKu>Qc_o>JrJ&wSW(lf9 zVQFG+Vi9OHJa`%lYDiUS5sI>;)Xa2Lfz0AUR4c#W!x6H`)46wr+XjhmJfrGf@(kt|Nm z$WP7()xgLOP0j~x#X?qb3TW9d zx)Z^ISXHLy=cJ_O6`}eQtUSFau@c#Cs9U;*nEf-)_^D} zEh;R{&n!kss$fl+i7O>FwLqZ&ble!SV?lz&*_D_!XXb+H9@MbUPf5p;MAASjxRZ)9 zlTi{$S`H|cfvP~%3M}P$sDpNs&k;tZj7GPDTq?V(Km0$!XX#OiPPXR4OfJD<#Jds(JUxX60 z7-=^ru`CsI$P==SFfmYM6=$Hzl;>dvX%1*UP$4-ZGc64@x8{KQa3E7q(hWouqi}!< zqh)Z2C@9oZLHQO-m_b#b z0z*I{r6@58MHHjX$Ons{`w=sK3KDZtLERh78W19bUPXaLu?8+!27Azg`Zkq`pb#iP zc6C8&VseH;L1|hVs%TLu3LmZ3D99;AiHL&ya?p8n=*a{##i139Mft^*3K)%^qWsE4 z%xqYkn34jTU@ZdevO%7oO@=z#zcMK5rQ^YT$D6I@xT7;BMKg4)g2o>z{hsMqzj5b zbuDQ1Geb&IVmU)9bi5=LdAuYQ)Lt!1Wk^+k4vwUzWJ0I6V4Hmykc7Y~gdsJhB&moY zH8+VNHMgLok|8xu0UR@+I0X+?Fn~$$66WkwkUV(5B1Ra3l!2PTa0x_kFr*fiCgv0~ zfY&Inq!%TE#sHzb%slWkH!2S_Mp9IXCWciXXleyKoeotD9$3iCOJ{(bPQs8{lEIK# zT9nU_T9KTSn3>A}nWIfjVE`Te13Gjj4cyZPwbe887}9cz7}D}e7}7ukq_6}J=Rk4= zoC}(|0}YrbB^K#G&Vyt~E6Qa^D=A_~2Oaj2nGEUEA}uRtNH54^fDCAX%EQzYhV-J; zM9}u?4Am3{(3Cwa^=IaR552)rLmAvduAv~wVvAu~6f zAu}&A8FZ*@W>QWn1Kt%rEYKtIQV1x6jCO-mfwz5U=9Q%ufrjD12?2C~D`=ZJXw@m_0}!t%LzGL74+(Bo%?q6$gufnAxdN zaZue^@(BxQloVF!GJwaG zAP1EfBcD_bUe{c#09$X(kdv3q0NZ%P0@|#Y2A(hhjR=F%C@8x?+yL6$k3}?(Atyf_ zd5&9z$+oa#22rD#=ht%>&JgmKLS5 zxPn=!pf&_}`FL(3igY6AC`$$mLC{cdPAaB2sD=hj1*GTaCFUrA7NcfkQH5O4mK0@T zQv#0IM96Ax$hfT033^$l+KfhLcU4F-)17ndkNRMmMU znaQ96qCB%0az;F8Wfo{hQaWgyAI0{9f};G2%-qD1)SODtd8**Gsfo!YrQqoth^x>o zMA3s?NinFE0qR_!SXK-=POvx|v?8Mjv=9o#)zG8D(Zs-Ko}-F^=NFMn9B34Q=U+hS z7ChO4Y%xRzI?_~}3yKTqj3lNiY!aYRAk|`2SAfLQiW0L+O2Pdy6oWu=;KR(5L9JE{ zDM-S@lmZ_i4{8KJ%Sf2Nic-taM8K1q*n<%gFe#v^Q4|M*#Gw<($POYhogkE9O-7*M zmpn+)MGYp%E++8qI22n!?e5Gx@cx5Dg<$?;U(xi0ICU)%Vz}Xg5 z1c4@i(XGOn{FCzwitK#Vkdm1QN{-m$ z3f6@O%~wKB_eV7r+?_`aP*4}Y7}OQRETZ62pzYIWy7E(t!8se$s!YtxQ%EdUz#8r; zSQO$5f4F*(V3`J>NrH@L2N|l3Y=7DtPxF znvvjs0jM%eMRzb%22{&pmn+RfFQB2;;jYCX3Ut9||7K%)q#V@709}iKoB_dYKyW(< z(q>1`pkR53!H~7rXg(~@Qz%JH&PEYU%}E87DWJhLWUCOuklp5>SOXuqgF`b!6}D0X zJop1z9fztj4}2nTK~a8w8ma_nL60Rsqc(s7Vsp2x#)hq5!nWCI{B|M_8U&mY4%tmWEd0gN6Y>Ed(@! zDnKI?D8T^QPykv-h8!np`K3iA8KCpYQ4=VRx-&gBKR30cC^H$fWD&G08$FFeM~E;3 zFC#w}w8pn2Ga1EANS%w+oSe)8(9kKe`!WtMJkpzrn!F$*GH7uO-f96#btuMX=A~uk zWtLQ;36`W{G_^n(yeK&lG=GMn7;EN+55(joR#hqlqiO;j+lSG*0C(ZRoeBj|GXgY7 zfb3O>G-%;8idhI@>=_g+pPZTr+NOi45ogW?YfHUJ{cbg>U!7Bsw>z*QD%B3XdDEsV8K;oKv&f%z*>o* zC3Yz8!dd~q1d&rbj&dEY6w>V^qzc^iRVV_j-$pN#v9+QLit@3Q-w5GEj7k!GdJ>8k zL0z9B(EW*+VGJoIFf$mEIMz}SSsvVLNGw9FF`x=C%1MYgwt^5MgERF(q%n&^h&V=3 z1{DUKI-3p~RD)&~u#_(NbP>>yAh=b98eX8)5@-rQJK)e1fsP0TA6A8yQ;QSxigk-q zi!#&Diwh(f(E43M(%5^yNQU5003Hv*Fg&#ce7h=Y$yS`1m#R<>S`3Yx^B}!@Xg3FU z{}N3ZI2~YX2SU{0C>M(JOF@I9Xybg)s6vv&nJ^$~z~vflH3b>ay+oKv9Wqv-fVH^- zmBUr&K&6ZF^HG~+puv0WeHyH-$>P#nl%!Q$T9lTU4B8Ndr3D1qrl7B3~}#W!Ym2`mEX zLts?VpzUQCB?xF(71A%m%(-AWtQ{zr49+A{T7cO@f}HXUx`rUB+MnRH>DK`YoB@wLhTM1K?H?1LE8fhTObT5Kbxrk)ZhwP^(Cx7`!K*A-9wP zd^iS#)P>B^Fo3R918t*#Iv%?-81Tv#GvuX~gGYVy@)eSxmpFoE_VV%}#|FbTM?y9< zARj}=0=Ybr0Yxk%zkneRbWAbmszS)293VdYEKA2q(QLGX*LRnk-AouYmHvQ4CR2Qk0s?kY7-eSCGd5IhZDg z0esOXXrutbg2WrH1ubC3a3xq4pMVu0P5yzWEzu__(G}q|r+}d#u_zHtfUgMv&zGkb zAql|U0`dW*lZ9y;^tLm^q${o|Nsw(2i;%oPjLAsKahjc4q>u}~s}!^iIW@0@p&%VJ zU{jD@!T>JgKm@2y0?Bp-c{vOiCpD=SGZf?(fU;o$XacjC0kT>L`3frV)F*V~PCP;6;JY@VykyW(jX9|)>7aaC3>8c( zNi6~u0Z=aZn&8X|2rnryFE6zS%Fay6$;<~Qp-M~<=xQUd^~o8D1)xPP5KewhenCcl z9z+XbWFNGF5!B!Ur532dyyTox&?q%bDQK}IM5+k1;tDDZWHEg{|pr4~2L=8*?7C-31s1b!O3yU#yacI<` z2}9x#T@WcU(WIcUhc22A3NKK)L5esGHLw^&mjK5ZR>5L4QACWQNx)(gT^Jgz=)#cr zMH2-@G`bKt#?b}yi&8;Rk0uOD18BnF#DF0NPZbz4h~$ALl?$3Th3l*h;TG?o#pn?x{PclkMg`9kXrV_DM6-@%tLIWSH0bULXi&JF(K+-+J z8xTI&_27075+CFn7`Lbd%7VBZ$|=psffkziIjJlVA3&ra4u`T!lfb8G!FcfFoWNd% zHtoP{3=c4XdN|-VCzz3+1`z;tb3hIP9mNTbbxrWdzN$t^eo11EW(ou7$UxN;hN6;! zJcgoj(2~Mph2o6Fq5_8EM9{?qiRq~j7I^V(adJ`-LveCJ9z$_5=s+XLHqPSYk~{|3 zv`ukpZYFq|l%Y7aps1vX0lEPm(mI6r95g?W2$?!BOU0!C)D**^7g81D(pXfQlF9(C zf1u9G$S*2^9;U|vIxB$zd?g-C1eEL+Oaq%rHBE%C{jUH1GbPD7KF+9 zrFkWqDGbHXrANj2X(bAf6_N}fHfU8+aXx7EAp?X`NGwiH1>cAc69BF0go%K+7K0DE z0kub=2gZPQuIn)r7i8u!6c^-xA_;omHc~4CeAX`(VPDWSCRoJ5D;cqf2j}OeGC(>- z;AsrdtP?2xFo0HLf#My0`Ww=!EzlyIymauKD`XiLXd`uYDg$`x4E>sW7AMeZ4M;{H zq@Wm=5#Xy2@Jiy+>YNBU2pYT9;M3w2oboGhm<^Xt#c4ihWjE-|He4pa9L!fuZzXulW^TflO-?C?oUO3lHc(I+u41-wieyPYs;+(v_LYlB>6fKv_laB3Xp zgSHdlmcnUdW^oBF4}osW@GMEqB_xl}Y+Q1PwVBx63<(GvHV442wI(Ew%l07f)z?n= zvOBU8oW|tm;3|zEX91_CDBuae;1bZmEZF@IJ}VHHy`XafadCa@O`w$?5RZU7h2Vj_h2ViahTws` zhTwrbhv0#{hv0!ch~R;|h~R-diQs{}iQpwNAT7p(tdRnF8=(Nj;|O7x*AXIlC?-LJ z0wIkO7~s)97I0Gu%FJT`t!;<54@>hvJ!sGZ-l|lPOin6%$Pscbv<_%Q5_Bm+UWo!! zF;;cOgcX8T#6TWlz;|s zN|JIIN|HdUz)Mn#av4CURkIYOc@XI2AnfiVy*<5k=ArTELIQ1>a?c#4pj!L3T=sZcz?GHW|F(3yGhRh@?0p!BwQ@Cgm3wBdN%P?2AGu0H3CbY)@)MNfG!m zBXkEqB;Z@S;6|h+<`kzQtVm1D&CIC;Z^}Xv%*;XZds=>8i9%{xT556$l9K$QRP2!m z8fbyaU_=tAmz9TPN@gBtUJFG4RK|lgJi#3dnIuHm3_4*AapX8$Sq}6lE`&l*nS#m# z4a%lx<{=4!rVr6m87LJgK#$ZxQkq|m#6gPuoFd(lBqXU4B)MGh6a_*Ov^PC58!7nn z^1-KXV(}07pdh&KAj>Zi2IVK^fKIYO5-2SJxf@BKEERO^D3V=>A>-nb${b{g%!<^U zVg>LbInegARHP(W0Fi^-KL@e_Q!X>FI5Qwb`U;C122i3LdBEY8o#M9SIl z?UZnb7nc;JmLz8&nF8Lxf|-WU!o9c@Dcyi8NQ4o{Nvb3XrD!TiLMfU+&QM561)b0V zy89i;2+-loMfs4^`q6}oGZIsf6Ew&WUFe<~5F1=jgBZG?O*9||L?j<6iouhkaH-N9 z90d_X0y84OD@i~p3gNUe@GZMY#Q}T~YGMv(mo(h6agj0o-0yljTj0tQ&n!WrQ0t}s#L zEwBhN$Oc#hAGZA!RAz(P<*J|yxAL+XV0>_mTUK6BRKftARR)jal;@=|ROl9GB!UjT zg!;4+>WfO4gDX?>7y^p&vr>~wbUjma!ywnCSSh%JuHsSfOD#yu$y5j_O3VWtr2twB z4^_+sxyMJ>w>UjBMc1h`y;wIS-%25)q@$MNM%8)75MC9{eqmt%sgvweke{Yu?-Dz)3rdT z0|j7OYLTvMUUGg)W?s6Lf<;nh30FW)X;EU1E@;G~*h(R<0L(46HL?b+XfI04vDL^^ zP_$Jr)U@V`&~*px>;`S+u~G=g2eoPxjP(rk47nIUr@tyZShC~6(%uJ4mONOp4$N4K zOZ>r-oe!35c(AmILE*uYr4N>NKUlH~tYg!IrQO5{fpo5Vu(Shg-M$A)KsrJ8F4+fK zPo(f*$@~XP_B~kA`C!RZu=(pAKx9C7FM$UvLANrcf=)Dc&PXiMELM21WGmQBy$_Zw zW*|xx!WYQOkv6=8O`Qs|800>XbEZF7vR~oBl4TE;Ha}Rh9qi@#50>l)+r96>l35Ry zOod4Ig5A>iV962%h_Ar>-UmyjD}cfZWLEowCF{Y#wR8!Jd(j;L3F<~rKrGp(Kzo-! z$J8P2UJmx-`Ugwfk#>{A$K7$O0VgJqFG2D4V99i_F&iE%ZBPJ*(t3plOICmbZi&JJ zu>T3#iqk}RG~zNEG}Qo($|Vn$>{L+I08eLYrZA{#lon-zB{qSbG862`sS2tZpzCcl ziy2h)jMBh|ktS7^q(Zs5sp*MOu7|>dB{Lo@Sq#<&O0EhImTXW^^@W7Wevl8Bwm(=h zpFtHvr4ANl5Z%FGe}eQ)eE=d?fK6Y>fIrcJ5(hZvK>~FHSkrQF4%z_r8z>nr1B-5W zuoP>uR87I2GE?A(HK(MeC6?xtD1hf3l1ocKr<|06t{?zi(Oy}S$^fN{K@4z~fVg8Z zJce`>9xPc7_SS|6OFQ6cdEJAh-5@=nGZ4WGSU~r>BivS6OGtkZlOE!TxkUlrm ziq&8rwm(?13Ek}=rJz`Zx)H>Eumqxf16b2KkPv9n1Zvc_2TL1Zd35`OB~wAtprx3Z zdFfCUJ0SYNBqBY7)PV|4Y-t_tZ+wcdxtySZ*fq@og%rpeE8yv22RQaYnGmc6RJ?Bh z7rFbPetfWmR9%?9f~3)9;E3I(zy>=7H}nO-+F==Ykrz0_1Q|p|Sz&K~TjC$%FeJEP)n& zAUD7dO#pQ77L7xIvD0KGhF1D6r|9xRyyQHxRvGiV?cNFaY{ zVu*lz18#+AG8lkMO>B9P;la}750)-tu(!8oaD<*z@2KGH8RQ)5>*nJc!QiOi%HRmS zU&2u#$kWfA!BHW^)5irQ9O~=i7#hL=s;QSOgVg;yz~y@HgC%p3Vir{X>;OjwxZ(%J z5~zxstpJXu6`<-999x}`b`7|u0_8x}zz(Bbalqx_H;PR0HTn<3eB%~Mz848JN zNRVy=yJ0K1PTddJYsCNySxC}c0_K8JF}M%_`D7nhXw!qG4Gf?p4yqF1YNx`CTLEsK zELjRx(F^u>BPh^8?LClc2C%~Q50&C~1E-wrAlHH0FFQb`6ey}d z*%@5?z_o*Xz5-l7?F2Xapq6xktp+;)+@6{PE~~e~L_zrh5=h&@RxJSs$_8+BfLfy~ zKo)|GhLkm+HWVa>Lz-?gA;G-n0k}q*1=b9U7f@!|L`WVKB;a(Y0QSuq1(c|cuLRw~ z3l45blc4v(l7*0f#gbxnf_>izs_mETQ$VqqIA1F~Sh5BdFv}D`VE_s0CF`)p(b6Rh zjyWX??nRIWMmtD1B&e3QD>&wqfQ3OO>;%UpI3+`b=YYMvAJiUQ+73xqpvDI{X)gh# z39trG+<;;cmV_V$$U<;x&w<>&4ANqU*Y+Tv&j1^`9n@L_TQVJF9Y`@28+L#L0n|KM3kykfRgfkgC?%0? z3(@}A@nC5aD5HVf&ZPK*Xd584B`nQ@8&jm%LsEEAXcy6bS^};RAyo>fO#yDJg9GjLQp*bDr+F7gL>*TOXiR=Zz-sBTrwTfjHRVrtn4~bY%!dbe60i0GKwm~X|4WMua zd1X2S$WtKSO@FYo39V|M4biv(99W>?BuE<=(y&+z9${L#9MS;Z4=!8UK_hjbLCt+| z|AM^)Z5o2y4Y|St+*$%T4xD2lt$j#vLLz=2B)LMeHl)oB@4tcCIoSGZpaj1j9Cx6` z!a8u=K?-cpFa)H1*94BsS)hmmw@o0;=2>9T#gI@12Qet6kZvuweGeM1g*4SbzFq|i zUXW>^=GPizjuD~6;MaE-8JD%=gA}~kAR9WteWy8C6vF2MAh{6Ii30UFAW^p!+!}!NXQ6e@>_ZD6rEBMdC7@IY zDx|=!gO0z$`(4{1$z?Vu;W9WYIJ>%d`uI3Py0ze}4K95k_CS*eD1Ad(V2~sYiHC*Y zcm;K*6+pv`Aa8^G2+GnRHl(`=m4<~YTB;<{P>?RjxEhWWzJdYVzifx)->Kl(Sp|tO za1Rw!#4ZFUCs4)(VQ_$e@+GwI4lW-+L5y#r1EdHPbD$~`kw2lS32r>H(JLU~jC!pT zIGc8W36&ETovA_UZafCmMr z$qCM#pu7z?4;luL9Nq!0RS6mn=^f7j`+5#IEfDSG;&>m>rcp=+1G~8a#D>gvfmopE zg0zZ3?gi&z(CiZ=CoKn6Q{a)Zb>OlIR8)X+0g6GO!3R8Az#2i#07zBeO_W|}2~CC; zWb0skeNa3?%L({s%^FB`yA3=^2+cdIK-n0i7(Umx1RO!28XMBufix&khL1oEAaG*Z z1|~tJCnQTFCOQ>Bjsj(^g%C@pflF7YrQnnS%ErW*y$aD}25ADNW3r9k0j_+Zv#|<~ z8s?}LKWdl@X<35CSYWvg6eOU00BKMl`3tL-o!}y2--9L4DM);}Afx)zK*V7S z#(F{qVR00sPF(R|38?k44ib6bi0J^2utBo}G~t6{5IhRU@L)+BsBI34&TSB{K?=-e zpu_`;lC_W#IZz@2mq?(Za!C_7ul0f&iy)n=z}A79b)Y&HR6Kz^39=GABnHY(*yn$p zLARoVb16szycGw^l#n(QxLOBK{X#ktpb&&Q15yXTdjq65w84IWH1R+lg$#It8-5_i zfcymMeC>O%1Qey9!VlEo1-Hi0EQe%GNTxz`MbL_8xKly1;vkQJOF%671TyHm1TxSK zk5@2*MSHWfS~w+Wm#LCyND zU|+8XHQJy{C?Ji6RbV$mdVr8x6112B>|juIfClqXtOU2*mP`ewynb-GwseVW1$gn3 z9{xrNs1prxIH=Bs>124YWHKzpgVHT{s1-HcLXs(@5kHl|xuhruT%LonQ7<@CYydk6 zl$0Po0yQom4Lz8AP<|UWiqYh8?Ii4oQ@t_5@_G0XCKZ zYN&$d2Ed+Qf;=MtNf@9|2CpRm7YiUyfOGZ|$ovN+8Eyc#GC<>T__D<+Py-s279gD% z=%5~?sWK0oszCi3u<0NV!Sgd@Sq69p1iT;xIH&auJB;#at0UAAV?mA zb`ljdz>x+SYH9~3B+$%>rWJ!rVo7`|IBq~;0%-{}Jy@~|+z|rV3GM5EiaSV0a0Vzv zfMl?{1~RY-)di|0z@w;$6-Zdp5u_6e)v^{mxd4g6_26bEs6k1wiekt>{XURymh6Bx#z0(f z>Y>~=cyvOBCy-lT;LZqWmW*o208+kz3UP3U9#nQTf>Q?dt%9tq0Cha57+Bz971l2V zRSJ+EBqVEs3Jk0<1WKgf5me|{@CHymgSG~U$UCz^9ZgWlMg2g66|SI&fD{eTHYuzK zol3>PTL5j}ffMdlP+kR9G)urGJJnJcB$q;$-C&Ik@DLujWeZRGq?BYRIgVDoKv+V> z@Q2qEkfzsca4olt7GVS#PhAMEUO@e4NFg>K)YVr5T7td=GCVL9-X{Z1hk@(-)!@j5)P&$c zQSfS|9S=aQC`c;~)X0FFMoJEYYZ^EwV4a@@C4~*(>;hXz1Wt18AR%yhvI5*yg``W^ z#O-v@z%{68wC}-^)sWs+_k$%1AUz{Ul?z?T1!+q_N?}OLZJPpkED6-N1K9y8q<26T z|3Ty-!)cwMv2)zkfZYhnagZT(P!k%m$`LYb42oq?&jS+Z;GR;vIRiFP3v8n1pn(qs zkQ8({5aJ8a*a&#e0n{1;jSQmKlVC|uX9dy^0;NCbV9icY)w5(ZXzK*X>EN*mNMjm0 z`%JP$kiILZKMEb!gW816Aeim2!CFMkj@!l1kuvbYOpslW#h>6|6mTz+WP3n{fX0x( zjel?!10_9h7%{j)7hAd_FSc}rF0^!2fUc}`4e8N0KU(kEW&<-s$aKYsQ$gOZ2Pz;_qC_e35D-BpqdSP0B#Y`yj8K3N_P~P!QVN4c zuFZE+OVa*6Oyx2DCtpMN-obtP24d6@|~Zf-D22Zup1?XeJ#pCJUaV z2Ms8KMi2?6E0X*SY5HsctpZpAs%pU%H7H-M1^ah8xU~&kQ;Tjhfv`uE65xh3$WTa} zgGNkAGz(I*(0xQ8+OW^4fN~{zqXv{Sz@1}ou>*=zp@hO>!$)FA8$%#2wtb&9mq!s~XO>jB}XA{H{ zNBCeWWOEhRSXe^=lH5UySs=}@?gvXi#R-WKg58GI;9+La*dZlm!#hUv!5JO0kPzBG zg!H$-iw8kv6R0H$Y5zmUFdIYL1%zgsGyB?P!k|E`aaNn6vzZnT?DPJA-xSq zzZ8f*vyk)-F#wwC2?af9-2k}egcRf;GaoDgueX8)1gMw+HwGbz z0-_ES{*X0AkXQj#nUD$q)C<6#ZxThLDA`;K~{l&{(Yn{I-6x@u6bNx(HaL@|!k4DlqQBt#24@Nfs*XYG(> zhL8k`(%U1HCK*8ERgjPYb#doESlVC(X#heDM;~)Wj6_0Q4@n4fK*a#Ks)lD?P=*0l zI-sHhX+;1;8zie?FSziPL6GbVS~iPPDnODQxR!*}pO8!o8T$d1DUhrTN}0%A5Xj2o z{jhXC9b9OF&PM?I0_1SGeM^^s#*QG9GN4Ik2GC#?sQCd(YT$AVH0A_aHw!8Fr-JMO zg)3AFBmRv=s4A#1c7A=Ni%**~~o zgV?>E0lfYg60Pe%`3XEwip3S6#oKdWX%??a&@KexRD#?HX@t*(w6_pjqv356(BwV1 zl7Ox|VgRp!Lu@F9)L@_i4Fyo40^TbEZ+)Pzzvu_=90N5o!F4ID-vMdug4VZ#8!7w1 z%Y{KX3%z2)YdL6q2{bMX9#h2W1jr&VSTP4$^#mUjfF`GX;AlX1I(6Hx=-ZVrR~CSL zgD)J=O(5Veh=-vA0pJo3Zz!Xi4qu)?s z?4c$=$_j`CmaK^$PFUtNFxCe^;+P1-;FJ7Nw-BundE5e0=weRclWHcunR-&q!m@4~ zl)k|2DiS;iYPY~=^+|OD@^m_>dQqnM!R;_eyA0InBV-o#b%>y~hv4Z0NOVDmltEPt zxVH%DDudEFq|zcfkRXj~PtHNKl2Q|6 z(GJP4knSm@fG4Xy#$qyswK5hH;dL`;K$+aKg!BRyi%UqXp|O}iNj;4{CsDDU#^PSG zYHKX!kX>hEF^j~S8;c3(^*6bRiduC!7AI1rM#o|eXRP&Wg#l7bX-v7bN#*9T1F{z~R7F(U0j+pNA2350fv*by8RLK~Hv#R;z%sD7+`T9@HCw?Qbndu< zA!Ke9G+P30GcALRrDD?tQ3>fcKo)O+&e;X^i$EiHkm1y&prnF!P%~&v24b8XtRB(~ zfcEQ%F&A`p6L>!(sMmosOuG{{$B)ZF*fg$S@Te>R--VEkU?Fv6mrP~wgf1%dL|#-82;7OpzP$`S-3PJ=`(81;mU`wDrxt-u;)6^TK=v=~FZi6L|wK?wk48)!ZaJlO~u2|-!10-ksSod%r(>7T<=KFB4Yys{HC z!Vg{ty$(FqfwB4*G@S(65Cn4VTCfsGOB#~juqAKMbO31aA=q({#t>-n3?v*;76L$K zDDW;Y0L@E*CbS{5b&%sHAf*d2>jXfK2blmm?G-$21792k?VF(wgF_NIVnqVc8bP@S zG_4DoGemJK!~{fZ8gkqQXt@lmyz7826hK!AGZM6ecQ$xQ4CF8q$YddSZ2{5iAJFwf zT+s*)8*n^9id9gmg`^lrrwJNL@TLS*9x|_oSn3Lym_#uGv;qL^0Z7RXDudBY0TouT zIth<;KA=1EU^i4{g6_`45Ge*vYJtZ8z)K21NfpN!9;|Q#MO81@a!_`h4L*7Uw)~#h zrU0}71Zhlw4od^q%pmiS4wwQR{7-FzA$b^)06--Gq|pJXHX&zcA&$ufl{}zA3$&PK zCwONlxcCAc8U#912vq39TdR-^0%{~7ucgCfE+~IN_Q50OjX`A_B3(h;H4QSu1zB0r z4VgEEa5{9Lxf|jz(7p_a7EmgOrcy{M2Uou!uY#s95or%J{S4X^vk!7u2qd|I+>h9q zjd0Dr2TK+})PeTl!@~t%lX`E5MCeP&Kv*l=ndS9#ZzUgDOi%WdR8k&{;(g_d-e<=#)KDAcCrCh>IGCnF@dg z9VBW|GCwH&gNt@7eKJTw+XT)4ji8jfv>hC3pfxclqHynmx_jsgWgx{Z=vW)b3Cyta z1yZ1P!jFtx2R_0KlC`%(LKD|Uc32!jvkDO=ftQ1TLL9n!6cSI6su`3TASNwcj+mt1 z0q(GZk``DLVh3p95TsDv0E#n6`w8l4$e8#Fa0>-;?ir{)0tF3d2@WKofY$b4pVWcK zgBQDlR%<{b3=#t1XPtqwsa9Tcq0fN5Z6{$7^Ri~hw0LdcIvJ)W>kp`z|kSglt7rf2_ z_K7+UQ+H!l3~vFrY`D!h;YpfD7B5 z3|Y4dTP+AGZ9olMm>LE@=#3qq7APp>*D-+h#e!JSE;e+%3;38E&{!2{Es;MMKmJ<}zLNuaySz-|B;2=_T8fM7#_;I`H{&<3Osl#Ss#-7$1Q#)m)yH{iep`4}=71ZhBm41knX z&^3LK&Kc<3P#liLy=sl1Ry>Gc?HyCz|;*s zMFy0A;8_z9i0HH0puQhy3;`6Cm?nYGgNBAAsXCW{GBn8Dkf}e&@di+{P;7#2GebBM zHXRM_O`**h;14#G8DoO618K8@R=MNM`NW40!Z70X5IaJH-_wYIgBLcCO*PPUTEx2t z(!xbqrG?0$#2W*Nal|q$;&p<`9B_pOA4?_H>qyhOpd61VrBRXu@h*YQTZ#W>2KIoMQC1qNwpfbUKNr7zGahMGLJc&U59t6vaxUs<2_)S?WI!tM4gG;) z8Qf%pD2Fy;A^l!R5db=s2Vx>x)PanKNI>+0`1q{C-q%E&6%83rge1NtknjP|3P4Z3 z#Moi((2;>S#q6ZI4gYpz8Y9XZxq*wwaPJE$^-f09E zO`x0zjYn{=1~l@BK6D8QeneRTi2=wIFxjqI2cE(Los$Y_lRS3}O`w z=*TPZ0_H}z3y`k^SqmOw2X%VTcLG8Tf)oqrBZQ!)H6$m4c2_}~lAw^?0XrTD#YvzZ z2_!i7gU7@nBZAG4d!$IQmcqz@o(2&70hXK(E z8n%Ks7g}nA%N9@pM~TBwY8!aQCD{=Hneipb8PKA-8&uAMvNNRcg4`mFa*qg>b`YpJ zgIxD70TmgbT#A3h0@9H01+CHm-R21jRLD#eXmsSk641SB@TwEMRS8u7K!X|-qTrDd zlp+zS$q8-Ftp#5~X^ z5nV6H7zFsbBkoKfHDzyIvV7E&>0ZWxqQN2L%17!L;@&fLk2$~?J!Vd z2An%V27}TO(J>144JZw70F^7CRv{=7SHTw2f!6DR0uMZV&wV?d>9&%e_;o%#)E2zC6N9ZB>97ukhFtKlKtS( zo_&zj4Un}#0u{{fVA zARYqE0E2`f4Rq)=+{7k1Z00L~?gfAh8i23#h8#!%>KRdJDkS=#MGn*~#MBI=T@KpD z4sRpu2cOXZTZe+ft&n+@osb3IP*bs+1xl;XtOhyA2-4RFO-Ddm%b)^$38;q#DV)LO z3@9Oh4k`iXSP%!20}%BemZlk`h=2|vKuVs);4}zY(gTSo$fZ=s3yYycDJV%7oJ1k( zMxm)@6*x0s?$uzNsGM5*pTvhagnK{DWl zmf-W5z#Y+5paKtMBjiFP(6u?8;2BBK#fRXw7f7-n+AD=#IIEkJSzO|fo|m7Ss+V7s z4sA~$ZAAc`tO1_k0oRQ1Q3|Xz4QL1s90ZV@399lTUH|RiCL*kl02^pP*-ru~z+h3fd`S>E4q+4D2=m|*$w-9*4q2qoK)T8eQlEfs10&n(gp9xvAdpThmaE;` z!9^yh`~znqP$OwIC`v)S%qGb60p#c&X!w9i6;O2!3z-d|ohP8fyg?G+kpNI)z%dpJ z)(8$*P~ODe2t~AoKoJJMb{b?fSSvJTg4@kYK)D5!%AqARqzHu+UW84C6q=CMKV(Q0 zQb2&p1V|SRbi)xS`G9j1v<^bG7~D(8Rs2A2%qG(5pvDTs0ZTyndI`Mh>W0S!IBY=@ zFn`0X2PpvsI>-R1B>_wDnGPB%LDvp0ci~kJ)_x1Lf`v3gAS0Qe z5FjGd;MFu}A`RVUln_R%A+ZK0s#76N4fNxwkY;Yc6%Xn{caDud41qP56CbRWQ95;JMDO|v_UsAGBQ%v*H_oYMc2c_%GcK_ zI2h5CSq149Ax_}MZV0#}02So$Mi%5$(`698D)=yC6Liiv)ir0w?Nl3pMvUd}%9W;y%4;CzS z2sk~0atEYl0xcqMf@Lf4C7MeXgUT~#P6fvhc%*FwYzY%~Tj6>L*p0JXh78I>G9PFZ z5q!Y!5=3_iTtEe9WTt`koPweolI|cQUCSUt?C?PmNZSuI906fLvL@76{d`3hWHLNa|ao$h8ERU3aTkOpm7~Y0)y|NSpk=T7fR4M z5l}-Bym$&94rurf*OCI90M8C+W}sy4N9qy z32W$@70_G_T2BV#6ouTp)ZF~M%;aK7Xn;Dlh>{Ib)F92Xfmf4&Tnkw+2MPsj`amY5 zc@mO~Ae~fD`HX0NL4C3Y6ayeLTU?$HS@u( zKgdWOYEutt*>rHYg4&8$rp?wu8~xy{fSB%sL^1dpH1MDXM&N)g#ZvHr8yn!I^jN|L zV^0)lv<%t-gQWs&7bIalw|*x$3_;5sTR|NUP-ueJcY+(3cmotXdW_|C4oK?`(!T}8 zHh91o(pCW_1JLX=I9xD>1BnYAXxu>x2gnVYka>ORat}nIjyZ?|S%d=_1%Q@m@In<@ zlVBt=ED?aA240vz@&b5x9-I^)X$wyhh9p7gf*(j|O$Q(3x(`xJ5r_d&)+Rv8BgEJg zyjp9AY!QMt3P8ypKCO>Fy#<+ULCW9QldyZJC!_&@HYfmZp@3R|pfm!hV<20M;T02T zOr1!JK$Quoib4rBNHjo_1td^Ou@{s|aTFp*r6;(h11duof&@X8-+XxQ79}X*DGbef zc&&lB9U3f<{>^@HGYm9H58*?)TA+dvUy_F>O-NM$s^^fCFL=}eTmSsJB4gbZebn_A$(ZHVJR_Cm%+Aq{0v zSp&)C*mQ%7Wbn}q2$w)BAuNRv!6F8Ix}B6V1CnGRwIZZ#01=rFDKd!8qm;M-J+wj9 z1h~Nh8kGSBDJLmuBEngOVslDeoXRp+lO;kcM7z;its07RWQtSaL)u@w}KK4E_qPr6WqF3 z3Yus_mc)}Xisz$K{(z!*MszzRqj%juixPJp)PYY@{ zfc$2~09j2PpITIuUj*Y6m!_wu7K1t}kQooKFJa>vq!i!ig$Ky}=tU=%-V9_{B4lX* zmd*(!84RTi1-0EkDHt@{u^&_)f+7ogq64DpgI2WeX0XI-VbsfzS0o=o(@QjxdJp; z4o-fcvJy1p1(_>>u4@OcO94$+AjZSN1uLw31oaQ8222C@ejv?QP+kBV6I@!5S_JpX zR`4+rkQJNI&2-Qa2S^w|oR2gZ08#{6=>lr(f`SdSjtt+xw?cAaQECae$pcF8Sgz+= z19rkJc+(5gn1O~5TEwBRNQU=k7K7WJAg42gc=!kTfeQ@KIv8ld2`!)$R6$2&p?3`+ zZE5fYNZ@gK@S+@0`LzI)I>EhQh;yJzS->?RWB>>>!icIIoS3JBLw+$r1~MZ79s35i z20;Oc801DRH9+I>pfVH`V)Kz((U2Z5mgQ<7MN2^o%OF)1$RcpchV*lx9R{$yATyyk z2fW}6b|e&diXEO1LESRYz!xY-fjR-u8V_tHs3?WH7u>IhZDEBZF;E$Wat$V=cLynA zHa!445>j)6rfb0lv_sa&K{^tk(G^GorxCOS1}&JtNf;C>xN{5WbU5&EFz8k(&_OCl zl_bczC7`A(+@nZ24z#iitPvE2OP4UfQZ8hW5!55bm(VGS0Z4%k3RqBnf{bl~TA1K` z3JOthZ3qerkQzulf{HQ)*Sr$qPM9NT66PvQP+)<_pU_5CLDlmTg2PH7b3=d+@8>CWPp^%ZE3+f7j;;I#v zNFlejW2#NfOF=oNg_t0Kj^6r8t{&AYVhW z8bUE%=OB;aLo5X!xdXBqR3IQ0=zwAZGUJaUQQy<%d$^g7Xa4><5+s#S{e*z5~?W1DUb)!4goL2yqYNd{DC;Jk^Tgcu+$1g~J-0U1ojawZn3Mnd8i+Mk0TGXNQZh15@=g|A@iK=HZ+G6q7Nb0K4A zh&zkHegwrksGI^fZTEwOK*0@a(_*QjK>i1%9Z-!-oSl&T+6!7)05TU+q(C@>;5G*+ zh@eF|SQs*N3?4j$cPAiCJy5j?RVKcplAmN zDWnkw8VrUHRrfwvvK1WPAeUoV1PpCA;x->tWP@5ypiUa72!w z{nC&vs?gDPNGS}DQBVgM9HX$p2iyz|g>EnpMc!Z@3f*8Hir7yM+3F9e#K1K;cr6ip zsttam4rrefWHuK^--{{+fzAYI1(ltk;DthKs0T5XeQ4ybG!eLGcSJS|L>+ zDC2vxJa7oE6(ENdL)xH_ObBW)KvEmzydKb25pXPlrzk-Y2yS{pT1=o>ZEPcZ zs-VMWK`k3_U5kF#3u0gpvO{7Oq+{`5$#g4F_Z~9Z06IAZ6uRL24Cyr@I{AnM1?i81 zCQU%4D!k-_rhSkYBng7N4W5btwf!N36Ob!LQO9i+T#J(v3qWmByzMz?fRO4^M2LVI zETAP)AR2M>9mu(mMhT>T0o7^HrZS|zhwwMJUyRzHP~ZZ`45S@F6)$qZ;v77~1PVFO zW*>OrfGGHufzND!I0t0&qXux(A5{8*(^GIkVlq*I3i1Oa!9o|cLSh~|UI0m#kg!2m zj@Uy0Iq4I$A{?FtK^%fn3EJ)l8G%G!)B`W_;0<3aOMBpoAVt%3cqsrn3|9es-4Q5I zKy@A{M4*K~+(b}!AAJoKjs_;yg`lV@7~~jmo`E?AybuzUvLG1&61pf&abo%uuycS) z5|cnnRUj*{Aie_G4~Y$=N(R!N1J&T*wiaY%4`^Hk;Sz$;0$J?>J|Y0zK!MbIkW2(G z>_H86#B>ZIgAiLVkQp8jS0ENAP~rpv;SV}-Vkx+Du@5r(1s*X2)jH6W1a%AP6)(8W zzY5f12Gz%qssqxpgqjSg*dfsjsY@|-Wr7_BnNHsa?$troeD;Ey!OK9qKf#4%SZYyx zQhsqNWUCvfZOH&B_2K0m*1ME+HD1g*Mw4=*{Bq5z}NQsNm7K8)^mdz+@z^jg-jZ;X< zgfxyoi=M%oiI>2JOCga0ZFNEd5i(l8AJkF-H-GUN5D9HIMj~2>OTeiPGFAy{@hCi4 zG8t6tfa-P*kcW>jK;jju1$trt_zGOmx=={T4H|)hOjJPU5Yj@kj? zdt`S(LLW5TNmOnoT*ZJQ64Ho=6wT1hV-QX+^t>C8r`LnZ18^I?4YVEx6z(e^{S^2 zKu6o$1dnfUQwO@G8+1tmbOkrK5NZOC0`)>RL+=Fn9F(^~4N~w1MyUOuF=9w#0TQTC zPvQ<7P+)=cD!7Eg?rx|Wn8Uy+1~M7~&(h1mZUlt@vYWxq1n)*g4oOfG3sRzkw)Ml> z{)ilB&j8sJ-UMp>f$|w-iza9lCuHd(Lp@ZTL zP`?@EaZu95Jp%wL*uj-KNGWuflYr`Yx6Hg0s8e==>H|>znGO2$fEGHqQM93myEPGMG838id2Fe3qKY>CTY${13d5Gm0AO|7J z2!uE^bwOHf(9}g<-U2mA8VMFCl3Il5s%Q4x|eQiW_iAg{WRZ z2WTNCS|OL6f$l4Quw)<9LlC1;8jSEbL231Y)FayNa5X56c90sZtxAx;z*QAPq5^2e zR4XX!f&@X8l8!u&ZPDh~(EDl-!0&xRq0j-WgIanMy5rc+fbrdSV;*jVA#g{I~ z`lanU3YB09NZ|?_u3p-pqfiAFhXwl5MutR%#N^VFRE9)_=0X;mfTH8U62!E}8gT8`0L})Wu@=aPF3PkDSTVR_MU*y> zQCR4RE+}-CEM`b7C}2n|DrZP6VMr`3$!ADPOwKOONi5EQut4K^4B#Fwq#eBC0eImc zB+-CUB)CcdxgFHg0uSVXG9Xk2UTc9)+JUq=AX8PKeiwLp0#r4E`jC)CkC0Y2s6Ype zsDaCL-uo$&x1G=(r<+v*#%k!$dH^^P^^%XpPUU@j>C|g zl+OTj4blM+xKbaI5=e~!T66^8kqjA^0xgz;O~!!&8WegABxrr2!+Z6wA1Mc0i5<)l8Ui1S!Qq4RdfzgVG5k z>0q>qVaW(yXo7li49Ph;49Ph~$r;5(49R(A49WR987Yuuh#<2-C-Q)63rMbllzO0@ z*^q<_%8U<|fbPQp*Oegm?*MlNK%HYy=7i)oNVR~dUcl`IP@;t9&pD9RKDZ44D!d>? z2dE>-kXTh(l**8lnwg%;kd#?mSPIHDh+=^uDJL;6IU_YiAu%U6KM%Bs5L9%4ODvEx zAq73iC6ME$Amu0A{B}?`09?{c14kjKqJdn)3JF)x2|3_!1w{a)WQWw}pvEeaMadb7 zMI}Y4rQq>M@Yy~f-+{JgLrNcTFfQ2#=78o%JHX=?(96ic)fA+V1vwcqat8?u(Bf&x zdJ<5p2r>f<8ao2DXTi<}&$@yf2MQ7_@+g{-91Kc{p!kIv3yDW)Y@p}?pN|Lf3^WX9 zfszr(LP%WzG7?-SAsL1elqiPn1Xl*oN*q%g$PCbA2dYeNVmfGRD5@Yh06IXu0Z@7Y z9Sj9$o_-I1bH43&CBiIgn;QiXPC$eMppm3NFz3 z3*gnKkZ}uWDx3pbECp%rf~IBAlTRzS>$)EtB<&38iJ5uDN%=+j4B*x%^sG}9GvUdi z2kv~h5ah&MP@4cfiG#O%!~6vrh(U50*x!)K6jDNhsuIXSLg215xMc(nT}XxpWpdCd zQIIwlXfG*b5EIhqg`_S}AprIVC{KVZbWn*38e~IBm+)0YSV}aM2!^bChSWizb=_b; zfy{>Hw@y%o0`Wol08-~c5;!#5qswYwT`0vDx+HoMM3=`Bhv-Tm5ex|f zMDc+|6~yoGm~8-!c0vbyp{WdAQyaJuu@91MAte($p`)usls{+%3%bH~SPu@OV+mw7 z8YMrYYr&G>L9q=kfkFDgRVpa8frqofBl_q83(5c>hk+8udIpp_0MeR(bl5gPs?_D+ z<`Q&a6rR=uxD$z@7|}q$Vp1D8mG^=}6}+8c_Uz>UPi=8-Df;<2YQik08L82d&H6Tl6P)vmAoeLg<1Fdkzq6Fdz za2psDFp!QpsNcYlTu_n+whVm0EochkX{g)$%w&0u!en* zF%AL_2hA`-(mJT2Op0}oCPpu~od^v;bnk%N0S*IrIAOJJA-GfowNICV`@yjI1lLx} zz?Du1q(d?vGM^0@9zz-agEUpTL1ikqkqnv4g{Im$U}K@jj6qgMKu%l&P0gX}gxC(* zSKatv$uvmca}&5029*quQ^;Vm7U28@D!v#}p;Hy9$Ws-m3Xo}vR0a6F1U%dzl@#bu zM9>@zC?P}g5U9cipIrq?ji7BikOA_2pwL{h12U5VY1ku7fG&yvr6rIqkP(m~1yne~ zL_tL^LuyJ%QV~OHZW2RkZb3;ULu#Hv3TSQtdA%`1Drie4q;C#tuY*$(sF*@oy9y5| zNX~^!FoPlm+$@16SkTxixG4bg-wtT{f;Bq9OH0uc4Kxox&ZYo`EO-hOlsdur8RQJy z=S-m`G*IS;jc9{2G^A|=I&clVf&d&=;1U&_cb6;%uSNlhLds~6Zy>i7Yz4P=L5uEN zK?N9Sj01G2Kh7{f(FLylK&FBM6C91ugok1l#=HTj!UvV(NK*-^;5G6LsU;ZxTuor9esHSY2F}BvAO%MubmJ|w;RcyshAbC=mLtR%lvb3>kX8a3euuaO z%NkaO^nyGFNd5!$k3n$;YBE9kACL?Ts*yk`4N}iRDm~~j3dB+vh78pdl-dkA%$I;K z`va{df{4N@Fi=Sk+TjIlP=Y2xps62JD1k~%aLI_G36hIJlULwQI;8Z^NXbiQfJ`(% zb^?MX=O7D?p))M-_y+ZBP%h$uOfN#_%w~amB%q}rpjv$ixD5(vFzt8%E@{z);58y- zsuvV=;DQ>wg$0zFK@kW^N04q1xPAir3X&Wl9&HDe$xA?`I~EHd-iO3DsK>&PQIZRq zo`W=>z+?Z=5*Ac`fM@bDq2+8Qaygp`EoU=f&2I<&ByanpGjzp}@u+rCi4V%;(C#gy zaS4fKkPzr9Ff1w|OX22%SH^>~KO}m)A1r~i4i;e7f+%WJsEExD;Bpb-iTaZrU0G766u!KX-I_d9r=7`%cL zOT!eyu43rPHy9EniAh-MFi0B^G_D8E>d-bBsQUwPG`xt%(&>Rr27+2=khV9ZbOdc5 zfws^vdMWT-%pgU`7C`#%pvCGCcY_x&fD~YJ5OhgCC`p6TA2e4&iZ!@1;f-ie_5wBf zFdPGJ(18p<@hwq?Lkb1Zyft~_@Se^pfU+!26*-h)KNnb0@ap~77S=f z4n!rmAqY|l8NmRR+>mw^WCU_5q-WRwu1+9LLr^mhQdvOOF+&@7aO1!`6+np&G6nPHYg<9HA7E1<6&QH%0M%!pyU5e>OTnu&!0W+5hJqGoL+TA^QyNnALuyq> zpBS_Z2C;4lylWSv6I2jFx^w%%El<$F9pEMmsPYF@LMR+?sQ~IaLDC|mR|;NYl2cif zQjo`xo0wdb4;oJbZ6E*_!=PRF;C>XSg9XtKK4M@AL^CM#QMz)VbBZ8Cvxsi(R!B=4 z()0zlE5XGgq_Tx4Z%`KvlrLaa7`Xhz)qcgL5VY?D6ejQ#0P56(hr>YL24y~U8A!o} zRR4i0cTn1a>I8Kfz!?QJ%?;Tx3`u`bc~E5t4tmhEImAowRxc=Y&|7kypq39P>Xtwj z1)!gA0LfX6klL*uyqgfT%mmz+Sh5fthS1#=Ab&!Xt%Fs|pq2u-LI6cSsOJUVDGTxq zXovv$3~-1wQy+lG9Y9B3gBtVT(gAzWg7>O|4m1T#G_3|Z1JZthIW|hP1Rm z1EMJ54Aub(BS`BLQkY`bhvIB}3c+j6p{;c6MnSSTF;;?{2J$J$W4OHpaSdcj2ND@O zKpK{S<`ERY#|3~7fC4pP5J?uEho?i7pu|0jGNd!(!G?i72p-viG>{>C9zhWVSwXrM zvf&y<5gIGNI?&p(8S|h22kq+bmRv%&w$%`pmGGXdIWte3{*ydLK+k) zkTMQ@?G@PXkgTv1oNHDnXlQ9doC@ijK^Dz}?nMRXTu=^L0b0ESn$B(q7p0)l9Ow~* z5GCOC!Qjk_UbI583bbhj?bkq78KKA^P4p}QwQms3Nl1i2G8SkhF^V?u5C|w>K{Bus z1jGkh2uV*E!f8c`*(Ie#IAlRRALL>Ur!r8uf~#Zjfn%Uhg63@nh!$|W2ksWIN~GRN zQc-FdsG|&)x{z@M zNb?XeN)O(559%`P0PokD4v9_hUP<_^b>Q3&b^8oR^BXZ;2U$@IDaxVMJ$gJKax=tq zETspiTzaqsRO+D=d7u^tc+Cc+VFGd;JTO7S_-I8JB(xxE=Rh0^$$Sv!L2DWX4F!D# zO~}yHesC(=2kLr*2lc=MiA1FrNbe4xYam4vBpz`mCq$-%gy|~G^aKe%P(vTlj)r&= z6d)@=b1BeXE0!>UPBeitJyaE_-h!O$)C$&%xFHQ;KDrEO_zW`a1j&D(I0m=uKttG| zstHo2f#;||d0;VkiUj0lcn~41-2qxa4Q@$8b^}A^dqI1iAh~cgq#Z`kPV@o}yaxr8 z8z7DWm+heGZ0M1to!I4xD?D{U>vcexcoU@MiEcNz4GD`WaH|7y3=X7y4h=3Wg&IT^ zWD^*uHwYft0NDfSuYpex1aYDJOCa&K5Imj)I_C)7v;h@spm~1=Pat{4*R8$h`dlm<2+>NnKI5TIr~v_%A|bfKLFaP9+n z7Bq|x_9Aq)8&pL?QXixr3>rTJiRpq0bqqJ7mPL-jaB+{+$OM_S1ZogumJPCDRdZ10lbO?veE_81_Z5XfHt@xO*GID1mtQ) z&}B4j;Ep16dkhxK_k%MQ=+rxKixSB+$m%IXlNdSVp*22ecO9fWg{;iz0c}zPH$NeT z?R*B5HXdYF6H-k;cE>}84MEKSc(VsmcY>DXtc8UwsHd#}UI-5!VE|hIs^~#U31mGe zg)Rj*GeEPq55V;cmYFBW8lL^If(EkHX9q*Z;e|(fQ?o%gpg~4xK&caaKrhH#NKydB z?t`Tb8jm{KKs6iKv7lx+XhaYaE-3XXq#p`NUJx%r+7F0A23B8ynkk6!42a+18(SfT z3#jW3NkZ_}8fb+C$d&M34ya`SUZM&f(NYRlQqTbJjs!V&HmKABWkvAl0IcZ5HHr>W z2udc9R(wT(}sDegCV2w(U zI~GGS8)O(7a##k)SV-YWga;sY;c!+ba$k@*TOsCwobX^tBe-k?1pt%}i6TV#Nk}oI zVnV45AX;#^7ZSzbnPOOz4N_P^a|fh31RD4UwHqMaK~N8F31l=06sO4L&I(X10;<8F zMFVL038MT!QH|7T1;q+t*l~k`hNGVgD2-tsmIN1F8va2b6_6yf7}BhRT)d80n*eVm zL#E+C`XI#;WO50j9F#i1jUCiH11UM7$59|!V<0oYV_Zm$6NFMojRo0+0;)eCBc>;~)CZWuCkhOH{y~uGd_*AxX}&apLI>m$P`!$hY6uM?5=wQL z`j zpv(!09Y{u50?7#oBO$c~r1P>6ZV+fmCZwGVu?bW=L24SP3}n0!)CL4Q0HPMsia@sx zvUnV2(<`{{0L2~1Igq*obQK|b#g5)VmJ1ChIl=;C6mq48cbd~6a zLNf`v0gzq;B+x+hEI2elPKM7*fEGfbcm&*s1#MVCPoUs3XX}F{pmhQuv*7D_LF*MD z-iP$6Aax(8-UnL;i9ApN1(kRJ%J!gk2gF|R;vbMAkPeiH1Xm9r8AxvdRK6i9GwhOB zk|-!@u~&Yuku{JNka`Pro(D)hq`Cr~vIU-&1}Q*P4j=`PL3vPtjkESdmn64-M711? z2T`&ygoAKwCxw+GqO;K#uF1ZpvD7w;6R)WsxU#apli9o z=@7IK0DG?!UP*!$0)e9o)E$60Vl|{ZhnNW|mZ3dd@^qoLyFhgZC{7@`Y6o_^$z|xQH=7>W;Ow83_O0=3u>)`3XH|*hL;}h(kje^?GiF0OCtwOO43AbBp~)h~<-z?VQ1=O`H3#lz zW6vl!I*@a~#z0npgVt#60C&wnL*!V7UZB+{sG$kA3B2?bG?oInIT|t(z64Pn6R95T z0dSIooHYjxEJ)dkUK2p7WzZ-CX#NJI3!0}P0Sg&K2CY#7?Yx8}dGII+c<%vrKQ(|7 z;Sz)@bSuGO0fj4eQHHaog9ffZ#S>@%7t(h^ID!FLCphzf22&KkJqYMf z0c7+5F$Rob1UQ?5nyZkVijX}}pt2s4Q07C1IU!!03obE1g(~VO9C(EVqW%D{C0+t) zEQ2x&xV;SW17uVOw8jQh2_vjx$jvKF02L%p2_$n?)#R!T&P(=lq00-q? zQ2GMZcc625!GrXm6ah;+ps*k!im+M&S;h=ntwU7{L2d?Lukm0B$k%YIK|X`DqUVEG z+=D82(E1Z_X$RU(314^wX?TDV9F`;H(N1v!MJpnyK}%@pl2XXBrrF>K1Z68oA_A4L z40)xwkVB8aUdJ+Q134BFF_HsI-JqR{h~>pF(I$p`=)&)OwIJU~2rg$p zGmXS-kOZY`@Nf+%IKjykbSVnNX3+R;8)(NoSOK{41acOrQwHfT!H+%$P0)g)7p0*F z%RZpk0(D;rD2FUE0WJN46avs?SdfjqkOMxj+k=vS30N{8(g1$|J_jGK+Wdl&yn;N2 z{Gyc1Jn;EkplS-N8(KrJ0xu3j)X?xXK`6^RA<+y8&=uh6igwV>53v0xCV&GUyjcd) zrGjj=0F`~vX*+zz!XpPX075-uAxq4lYhzK21-T16&P|0SnYbNKq%DXn4lY(8_rQV* zNfakD6eJdbR!hVC=O|;|kl=@mV1qWT5EYw{76+(I11Ap9;ZPuJ@!0_ChmaA$2%C^S z3vCV1)IK77Mr1UR7^Fmdlql;9Qi~LFGjqUOXCRFx_yp^=2TPVP6r?957BLj0gLcM1 zM`uXhu84B_Xa`Q?V3P6iyL7Rr*)FO6<87vra{ns9aF#ygFt60 zBF`E^Qz>|t5Twhp1Tw)4X+lAowU8C*s~{aF$a-whWFe$!22LfQE-17s56{Jjh8CpZ z2+06Tz>yAWbuR@?kb>G2VE=$Cp=qH03Me)}T~tV~6VeS_0e2L{6nOGn3vOgJfrk-6 z%}{t-1)^>#vNUr046?)s68@l$HN=VV6NC0WSOW4AB$hz!1kg$sP*)f<+6|k;1NYq_ zV|I`-4sJPUejQRdKx}}QnA_o53AFzUyuS_PT}VC#*$9abC?C;41$hIs7yvRJ16q#& zaWKS}kj5sc$pG>SC|E&;f>c4~)*wvF9FSkfRi+6O#yhF4LI)53u3U%5VwJnIAs0;R4IU+51!9{ z0NyTvCFNsL3~>SW%z#}v?)-sWJtPPqu?9+C;0Zm@co1Sf6WpeTtv$qU3VJTWt_mK_ zkOYOEZLngj8Liq(XG=gJ&wZAt?1a_Iw6b3o7;yFNsj56{fl6+#j>&isv}3FHLul0#_b1Wna}4$sHF z9~HeIKr#qa^g-he+HiwZUC4t)uzUa>EksWqpmrE|MjkT4Hyz9d4RT<&1f|mgwgj~9 z7}_t!Vm4waC{{_3X2@bDPyvYDO62MqQq+N_sIV9Z=`n+D(!wGM>A)k71Hz&N-EW{) zBB;*>3S%73gJv!wf*xx)Z-WdaqFW59$5DEK;3NP#i~v&ig6^f*0bXzc3VO&+R?x{c zU>0hi!s<6rl3NZQQ3VasU21y|`Gic}&l;uHkpb-OziL1aZ=LV38 zAfvZKR*s;Toez$hmgQ`U4py-S|b3-QQ+zVWC^G-fkh!?xirMF zDB2;e0q+x3ls>*`XEQLL54{| z6U&gLDUiWw6bl%Nq1Qf;dD{)h^9;oWnRyJw1v#Ls4+>^blfHuiH0BH%t$-e?GzTQJ zv|9n`%#e0)VF~KEfx23d+>2f~!6(E(3$_@FOAiqkas{X z0bQeon6`vmQvg{DFcnz|BtJkr46PMrfm;=z&DM~iLg)rrs4zH&p#$p320_+JLVACY z^Z+seoNz#i3bZx}vQiU#2_vMI21!f>rBcw6OmI^O+lgSfC6Voi6tdv@27D+6yz>Q- zfYijG-2f<=7M>;{0}Rj>3#3oD9~A5$CqlyoJ*W`2gD2uZd*R_lD!N)o3W7v0#6h6m z=@M|Q4DZ1~wmX2PK*8+~P#A%d0=N`vVDL%IOUX?v%7!yQ1A%M6GY30C6WdFBA&D1a z31~J5n<=1j5@axB$_li|3^E-HUj&pTw=%9r|;MNeR zY{IK}6?pL^%xX|M4sx}^gQcLO7;s90PKm=Q2_2gPAF2#WB9L(_sIe=-o&xRi!eS?= z48&B4X-6g69jlvL5K43_!C+cLFx`rIgG^-keZ?sQhtFO2K&GX0emD+adJ^+L5YGP z12WGDg=Y+}V9?C~MJ#sHL9vQm1{9^(WkB(XT?Q1H*k#tExD+&RhgBU$q+(Y^M2uqB zh!UOHlz^r(u!)0v3!q^_TwzQ&g7eeT;2lQDx)w--AJMP{n++<-A%kh47-$7s-1}h3 zJaB^-)Qf;+Tu==H?PNpByY>f5=0H~Sz^Wh6Aq2e-maIiz&4X@)4x}#tSz3dz3BK$D z(v|>?)Ixf>i$R6$l6}}MgBPfECRb8)MZC3tEY;MdHE#@#i==|$t9^N3?-l` z(2}GahLWV5;u40E)FRN7-YU@DF`z^Snv(?83XpaSxB>?CaUm5eJb|`@nug@)0j(r} zY`+2ZDM6-yL?EkQFfaQ8Cn$Jh59I(qa6=H(twd=cql_Pb69IHI2SWlB%pgyJwo@Xn zEykx1dEgT?w%Q5lm_AqnI;9t%M(}tMD0D%M1IR27)H9Io2c(Gy%1MxhIHcbT>i2;U z)_~{)XU;T_Mqkkq*Vm95Hd~<@---#fm{MDQ6MuHkS@`(2OtTk4p4e&1*J@o7-X>=LJOAT zX2A!!fMObS01!CbKm$>b>$t(AS+K<%pu7q?Zvs5-2kN7NdYy!3}zlbHR}Y z3Y878BnH~z3*OfP7X{ghEq&osg_=e{XWN4h!d(Nqt`5|C1h;V^?pO*5y=7oWK_)ps z?IKVD19c=o?wJ2zDQI;UWUU;en1XcqAr%Qo4l?oux_cNL`Jjd=qD6#72;4pa1wJIe zKrJmuup&}0q*Y*=<+kb85Lq8Xrv3W zP!*KzzzG(V2|&yJ(X~NxDnv0TFwo^8o5ewy4l>_?g%24f0hI*MauQtGg7qORBn)9f~l>Kv!H4i%E}ACr*orhMuAukDuo%!!3S`H_G5#~SLoOtqM!uF X8fXzJQcPDuBc>7&2kXJZ#VZ&92LzUU literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nl/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nl/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..713e777c84ff73e725cb70f2261141f7baf5a200 GIT binary patch literal 126849 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�C z3QF&Usyo5R2%eX{$;b#^KX8wc5j>Cd9BSVuDE*(25xj1IhY8|dH6}*zJhlZBM71lr5OYhJAokQTF@o18G&3=R=hs&=F@opG9xy?|QJ9$#JYH|f3{jWN4AIxk z3<-w`%#7f57)zNU;kN^-?i@2D9KJ#2e?jGWSs?n9Ss20V1T0t>!Rs$vSRnD`!vfJ4 z4CRMI={P8z%EAa|y4B zn5V%3iEkGUM)3NOFb;_O8aWujB+z@luaYMr8I8^*4HzYqZ^FZ>w6b~ev9eE(? z6L=uxsJSy3{If+6ugjlU&adwx5K;;_uPc? zzwkoBk&6$aPJ<63?+WE7@Il;B%LfUsIZ*ixQ2I0#8D+qDNJVA&#y9FWoF9|}z;gcZ5KLSD!`z?ha z>imTu?n@Jbq{AK|NV?k(V)PI4B zONv0;XAPxeL?HTVMIhlfO$6eZevl1xn80W zd$UC$>84K{PT|ANx|5)k*RNI>-2NI>E_R05*DPy&)3 z+a)0OEt7!Qw->7Zt^_0=zd_|iBpJc$v9u*2@g6G)iMJ{!Jx>y1?jb0BLlWY@can^d z`4}mPdmW`9{wrR54Jl97 zNJHXvA5{K^G$dX>NJIS3ECcb6j10saD;Y>QhC=Bq8HoM$Q2E6&5Oep*KnkZS3@4+9#?q?KNHGtlZV9PDtU;1j>$vf?Fp36q5ugOB?XATy%Zqok`*B4 zG(zcl3Xt&HtpG{SR}~=c`k??ZUtJLrZ_bJk@q9%{{LWK^gxeNHNc^0H(hn6O`Qs;4 zos<$poq-a>|E@|9`2r z{z2vCRUziMs6xUq4$7~F(om39o1B5ce}_Kxjz~h`50U#C#tO zNPL!PK*Du_2E@GwG$8SFUjq`)T$+&ZvDAd5pFmBBKe99-{_lp0FNN~=LDk=Y@;_)o z(i4{!#J{>)koa=eg19493z9B+wIKE`(t?s5cj^(hSVIuQ3V=`w=bf#SLlb4+z1;Ss0{u|HcE5}!S~ko3G6s{XhxBs`w#Lc*Ox529Z~ z58@6NC>;x>%k&`j_v=CYze*1hF1w)m9_T^b^G6R7UxNCOcDI8*q}}YQ4{7HI>NA4Z z1IIx5N&1lXb1qc8P#@B+E{E!?(`N*)Ywm)|_v%CXF_ZNn?eGQqjNo;+E1>+R`jCFj zTYX6Q{?Ui{TgU(so@xe={)D*!#2yC&h`hT2q+E_RfS8+S0I{bG%5R41>xS~DK>2eF zAo0D_0OF5B1`ziiGl0ayNdt(#A4Ao@gPQvtD$ZgE>1Xj9Le$AZX$?b&`-}}C?y)k2 z^p~6rA@Sy82#Mc(Lr6I>0V=)~s{V!{B>W#3Lj3*I5K=#UGlZmXWg|#D`58gPYmFf0 zuQGzzx5Wq&PkW4@{xX7?cgzUl-qTR=n?{iEyK4k-??)*81FHYO5hS0m8bi#HHHL)0 zqA|pLEhueZ3`uup#*lR64^@|93<;N9D8IrOVoxJfUxzWo-F?Q8bT-2n;=UzNdXq6E z-5xN8#P4mWdGDa=e?nGCXjTr1*-0#3B*0;O(6N`l?lXuzo7bAO(E(9O(F7fP`;ii#C~fi?FpsB zO(E`0g{mtwg@i{PRJ;SKZVHrMWD2owgDE6k>^6nC_Y9Q2X9_8&KbS(w6?QX-KUB>i z;X9~OPWK>GlJ5dP&&aJVt%X1r`u@ zY=g?5wSd_F6iWYs>gTtFl#?2kknr-bgv3u2l+Ln*q=za?NceYJLgI0w+>;Ka3!&<&p>%^4#67K0{zRz0X;Ag^pysczf|NJwq4r*|f~1evR*-sw(;DI~ zRclE27(i(!Ye+f^v4*%S)f(c?Y->n(7Fa|4HNhI_x3`?=h;B~ zz0?NMUN~k0Deqs{K>W{Y3!#;5A^vf+g{Vt}@|$fT`WHj_N1*agpfsBuM8Ad|M4ua! zpJ4}S2esKj%Il?ekZ`_W2eJPRl+S4oQKxDTvERiWlK)cdA?iEqA?aiZl)oR!zYSIY z%^u=DF$aixa|ehy!4436ilO`o4iI%493b`2MF)sIUmPIjOE^OK#*Pqk!X2Ud9U<}) z93lC0wIih6a1^TUHB=wF6D0n%p|m-ac81daP&yh)r$gytC|wVwyP@=SCrCUlc7nv~ z7AHu4J?R9A|C>&b^z*_Al0W}JX&z??UkXZVKxs25?EU&X9a@2r7TY8REW2&XDx^*%^|5xLqLmRm=raUn;mj+^OQi$PmE5z+mM9sqed? z{0%M;^BG+s=~==RqEFTplHU}e;_9xD@YQjJ_}{`6;!k&1NVtT$Lfn%IrOR9)?r(R6 z#M>-aNV?eK3W?tl@Q z+@}B$XgsUW!*7JtgHy@jg#4W;>fAmOCw11a~-eIWV7&Ie+T3zQ!O zr6YVG`6&*nKFJ5-j!YkjyPJF<_49NeNWNVFRlf>q-Z~$MfA;u5{BsUU--eq10;>L< z52POa1eN~<<+J-j%;)!om@nZAagUNOq@SS%mDluzm~Z3@i8p&+NH_%hLhMh5@=KxW zT74n@p5zOOrx{Rlmq696@P)W%2h{unQ2CR-j10#a85qv`LgH_#Kg6Cj{*dt71LdFc zhm1?z@@HgdXJBBE41mPj!T?5w5C#T@odJ-1z!wOqzcd0N>C7EUhXq2yH#HDaFIELI zG9)uFFw6;r#5Y3_q#hCsf{f>y1VQ@Wu|bf0(jEjce{m2*{a&d0b3u^!`v_IX70k$B z&%nT-77TG;S};U^T`g(yDkbd5dP>4Oxq58gtLh5CuFi1YI4TGcy7bxu&2AOXN2!pgg z8p9y=tqFsSC)|Y64B-&}sfRn3oX)X)krf zKrISsLpdU{bTq?|hx3-R}jSV(+) zj)jc3NyS0Zxmz40eI>;~!ZAAz626sj5dA%Ika$`Y2Z@KXaS;2y$3endHy)DC;^HCU zR38s%hfI!#m^ULH65h+8{H;*>a6H647vmxR`2pptCP3WhlK`=|A^|cUx;O!1{1 zzIl}ZiH~;)ka%QBgt%8A5fWZ%P`+IvBpgGa{J2DjIVFjZ@$rsCNc;OhA|&4KLG^!y z(!5EK@<}xbQr@^ELBcIP31VM!5=7t3BuF@KNP@)6=_E*eeolgvLjuVVbF`8n`aP2& z>Qj>;?rlhhq@Nkd5Pch={By~WaCn{!X*Ua{K*sYeQXuY0OM%Rzc0%dBDUkH@F$I!- z#Zn=(Tq-0U)KVe(Oj9B87m*5yzfLHBRVpOjZl^-R=_OR(-&9CC;Yovpzi1jHTqV;W z>Xg$U@oAn03D3ARh(Bx6Anus~72lf%NuRf&^zSrC_(-QiXw!5^xcH|-^k=0*!mTYG z5?@QxA@P1U9pdiy>5y_lAOoV`H3Jf!@fnbCEYE=GpOOKIugy?(Co>@ZmB&zZ?3s}A zM+W6XLIZnT+7`C?01*;!i7!ks*MQfx$Tol8&cj zL;P_d8pi2YSL5O;OwK&A z)SL@B5cj=?(!ZeQaOOhdO(Yj0FAJr0ptN-^B;34mA?{3p@*8p??wgehv1e;8B)rc- z`R{WfDrLDE@m9>m-Qd60av2TEUtioeQ(_@6Bwl5X_#A?khe zA>p5y4{={dJ|sRDdr^S$PU@3v{)k+}hT}vS4NmdD@9GFl7vG-sJ#JzV*Ao{*T`I4oOa@M#M zl8&59A?kukA^9-}O4pS_%7qD~kaA&GDWp7E2j%a9>c3D5NtgFaA@$9RQb@S}E`@}T zU>St3Sq8}$_GJ)tZe@`49|@&X%OLarg=LU(a77u!-aBOwcYG*=nD?s;;trv5NIO}f z9MVqEEr+DP*m6kzY%7Pv)4Fm<{eBv%{$e>KAKoj6`1d_joUsBDZhRGxaMh}SqB$uk`?pj;+;gY`5`VWUpyfd&Bt7v|LfoTR32~2CB}9EuB_w{kDk14+F_gcr z65`J5Q1y4A@~l;m^rBD&sgE71AntRmg7_~BO1D=*!fQzt#9uqAAoD4wsu;oh_SmZ- z?r^Gxgl|?gBz@0=(nqTy;rON+Qa;PnKPv=TQFNdPw>ZZGia0umNJeYXc;GWH&&}?P-A6w+zbP-vCLcHya@N?HQE* z3Z+>ZA>zV~5O*jwLfm252yw4ZBgEd6Mo4~XXoRG{o<@i}WF{h5WZlN6CP+A_G(*-ixi&L`_hWT5L-NO&W=OsKtr^k|Qf+~>2LoCl<#}@p#C_{q zAmOp61>&yLEf9O}wLrr6eG4RBI9nm^ly8NkW0O{hd!kz*`L3ZAlFnDQLgMLeDs3LHuP6r4za!gRPs?BCuEG3RPGB!9o`hQupd z4@6wJ2jV~V9!R)Y^gzUnx0=~lTHVyU2w%C65!~-I>w|<-P9LPb zycjCJybsbJy$hw4`yt_!*$;8|Qap1riV0Qy}qMHw9w9=t@#2x+9A?bP^lwLm_V$Xr;knp}a9b(_l>5z1wFasj*GXv`X z8IbU9m;o_&;S5NAUq1t)|J)2nx$0bK&4$F=YJg>b+}F zefOdC*SV1J;GPGe)#gFs!EqkMzHBI6HV;zIHqL{T)4lT;844H}7^cr-WH`sbz`!vd z(oelUA2Qy-vjF05ODJ8wfRP~+biUdGNI1(cgqUx)5aM3Xg%JD07edlQ(LzXl(Xh%RaD2T4;@VJXD_IZ$=oOCkQ4w-l1jmqFF9SqiadCsh6blz(C=B>vAs&3m#G zQvQBe3JIStOBoq_7#JA-Erp~%?`05wW-Noaw`>{2J&jPh4=O)<86@4WTm}iplgl9f zzOf9Fzuzo__>*rrBwx!dhnQ!&91?F1%NZH$7#SF%mqYBEwF07l#R`b~_N;)Idte15 zT+Xk6`1=Nw|6m2gzb{un>b(z8eH<$x~LnRQ(*Nc?(xU!g=XRNI33V3Gw%JsQz~=A@TeL zs-ArnL_PN^h}sQss)>hG_Dgy)l0knng7)%R@`Bz)OcL)<5~8sZ+M)e!e-tcIvJ zTn(|$21>g?)%&c5m>U4)heP?%P<=_OA?Yg@%CCabtx$Rb)V|qJdLdN*awvZt)V?iH z{vN1#hoJoPt0Ccg6>8pnsQ4?W_y?$Yzg9!SiE$0YUxI5O{*qb)@vrI{Nc?L^>E;_d_}owW{PZpk`GI5a`|lh;AQcOg{W#&r<)?S|TO2+BXV4iX+$ zq5AHwgT&`+sJg#Ub2!&S+$Xsn;%-$aZL%I>zcZ8{xE|t;1Sr37JtSNk)mlx10#&zqJtW*WK;^eVfa8zKIX*a$6`HbUH~v=QQ8 z-Hi};8f}D>do~*(?u~-#OWp{H|ICe$crDxr$u|v9dh$j{crJs|+o1F@D18k|KZDxy z4QejKCP@2(Z4)GY$ZUexqqPZQztJX$d#yJ?{9zBJ-8Mn&^W6mTSL`N8JSIcc=Wl}K zw_+&2VH2d?)v^iFUR}2d($BiJ3DO=G*bFh>Wiuo^yf;I_Ctx$gp6Jbx_|4u7ac2!w zeb;7){S%?$(>Fuv<)xb;;k0uz#2+U%L-Ogx&5(Ta465(PW{Cg(LG5MQ0x_R`3q)LW z3&ecMEs%Or9!lG6fwUVUw?N{pdJDw8ty>`WP1pi)@60U_dsl6N#MgeP{G}}r|K5h$ z^Joji-_N!{!tM1INO=B$s%O~>k>}kC(I>PO;y%f(koJS@R)~59D6O*<(r&SUstbnd z58n!LXAD$4eJjMi?5z-gRzT(Jpz@ttA>rA(6%sBBw?f+W>!I=|p!6B2z6(%$ZbRMq z0Lp(3b=RA%ko5LrDUTovL)#$XcX}J7y>kg_|4XR)e^7P2+acj0wjE-x%yx)<+E8)* z?T~OY-42O=Cn)U$RTs7$l8>UG>XV@28QUT0B4;}!9oBA#_^*FEB%LpY%5R49k8Fp8 z!xgAGkG4bN?*&x;^L9u$GVg%6Q)~yMovXS7QjWOpfTWA$9T0Q!cR<`-y91J*yP*8# zJ0Rw6fvVrX1JeIHy#q2X{0T~H?S%9blXgP-LESqc<9a)GLgMf7PKfz0c0&CBbtlB1 ze|JLcsK` z5dTcy1u1tH?Sk}6&g_DWC%%T#th*ukM1D79Jiux`2a+#!_CV5+{vL=qrh6dq@3IFHPN91s=_hFqB%X4h z;uTQ3bq~b+NqZpfS`O8}cMrtf=b-$Tdm!QeYY!y;|3k&)_d?pw274jtEO;-ZKb^i8 z5>7pPA^w@V7t(HCu@_>_fxVD$Ke`tZPiOW*+;?j)Bwan*3-JfbK8QNeeGvc2KxyrL z5O-VcgQ)Z02XTMGK1g_!?SrKEntc%SdiFuwv1%X0oqM737xzKRgNIQ4zo6y|?1$)= z-w%l=eJI~^Kg9gV{g7~o-wz3=`u&jnK5IWD9yjiX_-hYT{?vX*dVabelAeVQK=j!j zfb5@&H~{hA!UK@_+He5kuU!Wq>F)Fah=1=w=}%C3_JfdgEO8LxUWJ2@csGF3wg(~l zy$(YBA9E1m?)-z0ag_dp5PS9>goOXOgAjXe9fYK}_fT{A4nh1QeFzesnuj3q=za)d zzYmljatPx7$U_kGk`F=b&xg{Dhamo(dMM>y^!FcyxOc%(NIKbc z6q0^-9EF6-eklLsQAm7TI0{KGkB>s~$2+KbY{wwsEPD*%KI>x;|GON6l$$BXAo;BO z7{nbLpz*c}haQK-Uj|gX;5a0HYL7$0sRt^* z_Bg~HTaQEhvF|t}yiY*+SB^vC>)vsQf4&@t_~-v|NV*h10r8Le35fZwCm`}6Cm`u6 z=LDo&t2zO3|DqF+_RpRZ5dYmf0WtSGlx8{!aUbtVh(5iOknjjQ3DI8-m7fabZ#xNb z--VNq^!@B4#QndaH2Wz?xCldOg;Nmobx%R+6Teds^+Bf~{*OBaaZd(Reeo%XKO0U# z(!qpNknmavrB|JTY)4yXCd*i;4CDbc0uJIorUDz zFJ~e3r_?z}c)FZ}gs=ZONH|5FgTzbvIY@dbIR^>Xo^ufUr=EkDyYw8yp0np5^POA!C;z65d4DJXs862zU)ExafpY19{o%~fu`qH=x$zP^dA^r)t z3UOcIRfzp#suMW8YOs_+GgRndf+R6_O7nu0d$oYY=xU zL22D<5c4grLDH+oHAr}*U4yu%?iwWD&b$T*-#ynL?s#+!l3qVvgM>HJb%=Y#u0zbz zz77c|>+2Bzg?bS4>zD%gT{2P#T+i(Li-_UUb;@&e*`sNKt zdVB`e$9xlFFXv5&d-$Pz2`FFgCd54Tn~?OPe-jcuwl^XE54;Hp{{*PIY^c8Cn~?Nc za}(l^$xwRwO-T66hT603CL}!e+=PVp!J82GUW1zd7;63}DE;>)Bs@57LDCifEl7Sf zxCJSFf?ME>v?RXoaJ_kxKz6}YN zTel(lAK!+A*X!F5e|@|SasSub5O@57inH8-qz8^W5c}lrK-8(;f#}zQ(gt@R=9oeG zR(Bxoa)9y!?m*H<*d0i?WZZ$cr}PdaKI-m3?CpWtGYv}5y#py9m)wD*rww-?@pceu z{?$8>@Oyd(lF!-hLd;ja3yD{wyAbmo??UpCKa`()7h+%aU5L9{??T)&9V))yE+m{* zLB%)Sh4_Cr)ciwGednR-A41i?z6&Y;K12Cz_aNcLcMoE|@I6R6lY!FeP;sMs5cgO^ z`L6dM_WRv~*c%3wkA<3-4i(RViWlF5_`CKVBwo6p=1+ji&%Ot#zn0#ExbNUSNH|`( z2l4+4sQ9mYkZ|U`4@viO_aW*`??cpi-iPG7XehtpKE%8(C_VQ+B>iuI>N^S*zX?_U z=03#ye^7b;2atGDegF|SdH}J{`2ocK@CT4|l=lE)ZXHy9@&ibGFNgAvJ%FUsTTt^p zK*j$*fVf-uAw<9GLx_1+4J%rd7{SZ>V=0nxBKZL}`oQIHbUG@-?4mUr9#OHpf z{E>%{cslnG60g@DLc;&yLrAJx~2>YhN-L)Q~XJj{aXTMgB>;R(e3JD~axKY{r3;uDC!A3TAi|Cdi7 z;qwP-F56Q`x)FK`v0wfv#6I<>5Pil_+U6-F-MK!6*b@uYm+=(h-%_Z$>ZcI%Tb@Gf z?|TaI|JzYj4Q-EER??a3=-~7pFzU!$1{jO1)f9flY0({XWi!zaW^O(0;Q9nbODsEgVH@vdKQ#k z0j0M==_643(sM|8^58k79sl(?Bpva;fY>Mh0+OC|UqIRkb}t~|7zw3gp>*O4NIp+} z!N?E>x?k`Gq@Qx*1tUW^0|UdK7m#odc?pTduORjXzJk~n4V6!Unv?wsk}t}j@^w(U{S_n}C%l5h;{vF@^-%scsJ^4GAnEBW zRQ%>ENcsN)YW_bc&G{OlPUJPjK84p1e`vghgs1Uqi2p2JL+rJKs`rD^QBZYhuOaQ! zY^eIY*N}K9c@6P*1yo%<)SMP5e+tyznNW2LUqixU1=ReFuOa^2`x;Vioq^JiUqi~> zUr>FLZy@oc@CM=!!#5E3SiXU{-{uX(Jx*^R?s0nqG1vDEBt6DJ)n!5T7rcSwpNcn- zaOi#mao2=5knoxL1`=*dp!znvfyC!FD188G|0$^aStxxOYVXZAkaFO~8%VnR12vEH zEyP^Ww-Eaj-$LxydJ74E{kITz+rNeA^Lq>NZ}eM;dC5?I`CEv;>)%4$+X^*z0@R#2 zZz18Z2C8oJTZsF2LivZG`cA%ugxeLU{u@yHpFq`rhSGnb>e$~w+{^tA60QR8Ao*MF z9VC7%-$C-5*E@*&Vxa1ipz71#LHtqr4&u+wcaU(H0hM3)4&t8m?;!5q{0`#oT~PH$ z-a*Qp%TW7Xyo1E!&v%gY!}A_uzVdrWxS79)=(m3lG1v1wq+IlU4{?9mdx-rdQ2E;T zpc7^p7+$h5FlewbFu1caF!V4nfVOKg{AY&TQR&CZzz_<$OqPLx!4Gs9ECb{YBG65| z_Zb-&ey}hwoM&NRC}Ln>Fkxh1s943F3#cLjTb_AR672kBN}WnlQg$iTn>wev9p1H&3N28Ip>28MJN1_l#01_oh9 z1_muw1_mZ328Jmt3=Ah285kBbGB9wlGcfqDGBE66V_=vDG7NNgFw~Ay3=9lG&~VLx z`ICWxL6wbxVIdOV6KXF=`vIu+=I~xPTUls<2&CCo8lI#o&$)IpzV_@)QXJB~6!oVQP#=yYB!ocv1je+4jBLjmT z3j@Pes9UE&-M$h^&t_p@5P*hfE66e^-U5}6V_{(6XJ%k{0oC6QrCS&n7~EMH7)~=V zFl4YWFw}w4A2h9ij3{DbU{GUYVCZFHVA#jZz|hLbz|hUgz;KO?fuW6!fx()cf#C+! ztXojK{Gt9#fQElO69Yp98w0~TMh1rEtPBhutPBi7>gQkDzXqWo2NHgt9^I-oeDcuoG&g2NMHB zKN|x>5eoyuIYtJCC2R}~+gKSG-mow*NJHHU(gVVaK>44Mf#E)A4?QCT!y#q{@H$A4 z90=<&GB6l1GBBh<)9W!d1_n)b1_oYe7%($3fZH|uK;;1|149+7z|k%7#f%u z80wfA7)~-UFwA9TU?^l}U@&B7U|7$>z+lV5z;GWLW+1zmnHU(PSQ!{rLe1c2XJFuF zVPKGgs#(Rt!0?I{axaf6GXq0B)J;B6e=lNYV2EU4V9;k{Uvbq!0>~O zfq@BX2IvmxBPR@USMKi5QoOsF-8W4K9B~`eYsHid7wL|nHU(>LhYEv!oW}u zRlgP#uS^UK9Z)%t*6U0R4DRd<4BG4r3}0Co7*wHh9E=PMrciw#bVSP|nK0@PLVd;U3g&OPClKc0kQdgQg3RUQ2cc zhF@$9409M57~Ub736h%#4IdDD6*B|Faz+LQCQv?OW?;Aqb-O4F1H)TZ28LNswK`C` zkd1+X7pexNAB5RK`2#8+$Hc%ekBx!hGYbR5Z>ZQ*76yhDQ1(Ms28L_~1_onLnFrF$ zz`$S%D*G527<7^H$6=_O9hevxY@vPyDX(K=VAug-FfcF(vN15Mhx#2PWY5UJ5YEcL z(1sKa(V#G9W?)cdXJBYzV_>)iQV7K*>&A8ZWZebFFuRip^OX+>`<{4tPBjT&~#A3#=u~}$iVQ4je)_6oq<7+m4TrT>ZiA$e9OSVV8qP8 z@R5aq;X5M(!!||+hAB)841&xI3~o#e3?9r348`mW40Bi*7_KofFzB){Fle(fFt9T- zFepOZKNIS%SVjhhJFJj92`(`+fcHj#+1_o)U{omLa7(`ha z7`mb6fYgHSC7%op9}vHkje+4esBQsqpm+i!1H*J?28K3P28Jz2dMgkcEMv3aUq$oq^#I3j@PZ1_lNPs8}{51H&t3$h~g=LG21g28K*_ z28OB33=BE!3=HASkUK-{m>C#uFflL`Gcqtt2DJ^?7#ITB85nY){;*+WU^oY5FJ^(< zLm>$|Lxz!op#d6ZFIX8E3ZQQ6U}a#?go;0diphf<461LK85m-rVo6YctFSXLoQ1j> z4LUc6nSo&uRQ+Wp28J{?28KsW3=At77#LES7#JF$=DIUM?!(v#H4|jU zWmX1;d{)SP7d)&C3}R5VQH%@>@0b}F?t;oRkU}Va#m2z!0P2o8%nS^CP(M6nWnf@r zWMDV}D({&X7;2dq7!E@1xyH!Au!o6(VGF2z!Op-?0F9q`C>;&Ti>wR`QBXhZf!cMS zm4V?SBLl-rD1RaY14A=Z%_XRq4LbwFbEsGV69dCERtARipu7u8yHK}*l-_1wU z+(&2(wbzJ^f#C@Y1A`JX149)f14Aq*k1{bZ=rb`eEC-d_P=8KhV_^6OwWEfOfgy{H zfuWFvf#DV#1A_!J1H&b#I?&yO{Lt_N**O7;4dR3LIvoP-_h4mU*v-tq@ExiTBnQHb z%nS@_p!%PQfnf>gerXm424NNkh8au@3|h<#4AxNf$_xw)VIV#jr>eqqN{vdl;85rh6`L=8f49l4r7(|#D!1KdJ>gVmu3=H>~7#Q-|85mTV7#I>*85mx&GB8-MFfd56F)$o}h84)U ze?jR8YK9C0AoHOveQy=)8&UTh2u?2HTy zIUqJG1A{5lOpqPkQ1fOnGB7MFfi-|wOyfZ5MyCr z_{7Y>5C;vvOcn+P5vUx7#6WGfcGDP_=iDlTm}Y)H>?Z{-mDA^uh|$F&OrSe z#mvCa3~CEP^9|_CEs!1!b_Rx%tPBhbKparJ0(AET)UC`=H_C$24JfUH`VJsF*%%m% zK=mXm14AM+1H%=NM;RCx=0nv(jbgaO%D^y_je(&CG^POcLmbrptqcqd0W1s*X6y_M zlb{-|voJ6yGBYqNW@TW|U}j*bV`X62#LU33j)j3?8`K|Ar3{9kI*O5jp_++-L4lot zK?)i!_t+R1JfUifm>C#8GchpqLG4yRbDthF1A_@W149cN1H(yX1_mic28Ij<2Jn8p zKvo8ZU#tua{Ok-2fy@jH4$v@x**_iBW@cevkO8&TL1P%8bPJV)It9#I&c?vd#LU3Z z&%(e^&cMLX%FMvv4VGbG$YWt(a0HF9FhTAZ0trt7_0?Dz7$$?tTBt!Qm>C$@*%=tv zK=n8i1A{6n1H(2J1_mEcf18nkK@95ObWqx1WB^?a4KfOJRV;%m3j;$t8w0~d1_lOQ zW(EcUPXjp^fAG0tpa6$Q2ObiSe>dk@m7sJE8oy#=U;u4ryvWMHV8Y74APtHms2P>eu)V^@z_62zf#D$Nj#5Sj zhN)0i1o@GHf#Ew;PKTL+p$ODY19_5xf#CsY%n0Nt(0#Rx4B+*N4(tpJ z3G56EZOjY|?w~OzW(J0f%nS^3Ky6y6*`V|G%9t1!OxYM1nxWwUGE$3;fkB^@fx!_p z#>dFOupcA{8drnr194?QeN`y`0BB4P>b6rX3=D;g3=IE4?F4oPh6}6=46~US7|fX% z7`B4q7<6YW)U5@K3=Ey1`~~VuL(Kx2t;xi|u!(_zp`M9>L5PuoAs00E!^ps3%f!Io z$H)NQ|C-Fsz;K9xfuRyfUni(v!N9=q0qT|%sGI`G?<@=qZ$N!*P(PNDfgy^Of#C}a z14Ak_9=f4wLH2K9U|^WW$iVP~m4QK!oq@rPg@Iuv$RE%!dcnxRkOEB`a;yvtUhE7E zBFqd7`s@r0b3tjBoq<6XYTi|l8<`jwKCm({7=p&Wpng|kVqgehV_>+;%)sy)Y8J?D z5awWKU|7Y*z>o=53laliM^GANU|`q;bw>bHei>*?63V{F#K2&~#K0iR#K7Rdz`$?_ zsurXlgwL=rFo-iVFoc4}IiU8MgCwBXhmnCnhJ}Hlk(q%Z3^ew^z`*d6fq~%{1LPiO zkTO0728K^iy{#+^439zWY^Xg)*%%n!K;06;#=x)Cmm;kppK;xRAwkA|=3dk@91_nhY28LA(3=Gzc3=G#n?Qu}Q1M1cqsJ|K6 z85nG!Zpdb0U{GXbV7LI~FJ)k0xX8x9paiN<7#JABLG>&X1H(d4`3q`SLd_6lVPJ5D zy3>;Za_{zIHU@^%tPBhfq5en(wJ$;Gh=qaS256j|m4V?TsK3R=z;G5+2Cy(NEM;O~ zSPeCEBO3$5Q5FVT6?J7Ao(Z;1_p6P28IU=3=G~- zf5<@Pzku=q)ICZp3=9#V^V6Va^e{6p{D87upz1;9nS;iCp7CW90)FfjBnF)(ZZ_3feY6~e^8FpG_W z!5nH{1*m-q)i1`%z%ZAEfkBR$fgzcNfx#Lyz73k6fa=`r zz`(EvNlu-efguX2CxL~5VLE7@1tt#~=VV}D$b$OcnVkWAhnpVM-%~+t21W*k_pA&I zEbI&n5zuhuVP;^+WMW__0rjasXDzTXFdSlIVED3=AI7Z~&Qg zmXU$sE~pG*XJAl++V2FV3z6&%29-Tb3=CgDcdLWue?Z{|O8cO(d^QFKe?|s|T_6LY z_%s^>Lq0U#_?Q?NWT0^r4;8CpVPHrBjpMO0Fg$|Vw*^$@uro01hN`*3$iTqK%D}Lg zfq~%*R81@!149`r1H%ng1_pap28RD^3=GGia!{)o{xLBy$b;IzQ1@4{F)-W#wTD6N z2Nni~G*CYe8U~3>3=FZ%3=D@@7#RM5`VXuO4C3qz40WKhDM0-+(0mdT1A{A6{YEAR z26Yw&h6bn`L3VyZVy7@LFsOj~a!~(KX`Ykg912-!JgBdg( zih>--z`*bXl>XQm7?v?GFi5j7FmOWEKZnv*P&2I=7#LVUiW&V0Z{>6G6?8V_{&}$-uy{4AlPvwNIEC80w*E)R~ci!38uX!p6X` zi-iGvS0C64b_NCmW(I~0pneu;oQ;uzp@)Hi;U;KYmVtqx3p6jl#=vkG>OPR3vrzkk znHj)$CN@I-dH_^MGcz!_F)}cmf`;z}ko}Ad3|&w@NdGw&1_ljQ28K*fUldg4g2vWa z85nBW7#LnKGce>cGl1^|1E~e!qfouyKy5Ej`vJ-q0L2$O149z1uL$b5GcYim2bC>Q z`NN?4fsFxt{~E{~5N3tSO=e+Wcn%uVWny6Pg8FR_3j@Ojs9$*47#MgM85kN_85q_= z<-I{=Db(*EvtpoX{h;z7u~N`@H`ERgznqzY!I+tW;T;PDLnUa;jhTTV7^+W@k%6Ix zg@M6^nSmhzDmERe_a!LY7#JAtu`n?3fa(%P1_pDeSUnp9_{^5`tPBi!3=9k#Ko&7D zFvu}7FeE_LfP_9WF)%CxjW>WeP+ZE)z~IZw!0-)}rkEKRezGty1VQuZLa5#|p#BB} z1H%$V28KYW*llJ826d?0N?92gQla8dV;OAO85k6xV(*z57?Pl7u3}|iSi;P}AcPcd zWef}qPEfO8`a?neK~P zcri0DykurzC;`Pa8v{c$GXukXCI*J@p!pj%1_mEce-vtN4@eCI1H)S=4Ki~EGXuk6 zBs(55Ffj0e=3e8XkcYv*bM69K<(el!~kBy9S9mj0F4W!Wni#_+Rq9#w;wbY zz{tSR&d9(p2~=i)9Lm7J5X{EFkPVGL(47vQ3=9mtP(9BW&yT28J-u96G4&%*?>B64btc%7Lsp1{yP9WnlORb=O-a28OFl z3=B#jzk%vxs9JA!28LcxJqmRLNbgZb28J|H7=qRwAcZqX4uox)85o$E85laC@uvcs zYXyzrgT^J;85ks)7#JRd`Y)^u48l+~AbsnY7#KdXGBBKCWMFWB+7|>hKM2(BgsN?Z z`W+NZ&!Fm7Lj6$=T06kXz~IKl!0;Y476vLuKx5ZT3=AR63=BV^>bsz{Jt+M!GcZg7 zwRe~q7+x_lFetDvFr0zf1#*`^D+7ZFBLjmWGXujl&=?FG1H&rN8~{iXig!ZYDGeI` zVPs%nW?^7h#mK-Q51Kn?VPJT`%)ns4#=sB`8iN6iAwbRNVqsvo1e!mG@@3f>7!EQq zF#Kg?V3-3Hi(+R0pBv1<#=sy36$4o-35}yL!qs6ezG5 z7#L)sVVB6r0KO|4B)1zHc9$6#7}Sx>w*a-ZSr{0~Kx1}Lea@iuDNys*g6bg9yfIYn zF(U(m1*l!h&cINHWcME^`w;^J!z|Dk2q>IEZ4U+phFzfXB4!4LawK~}ZUW&IAOch_ zf$B!68B;)QEvS1zm%nWU#T5es!+ItLh9^*WfV9~`{W}RXw#drBa2mAEfQ^Ac5wwno ziGkrVs2&E5VL|-@)&sR;0jSN(%)s!Mje$Xdje((?fq~&ARPHFK-OtRx&&}3m?P=>lq0yLKiS{DFXD*;uzj)8$ekCB0apOpc8rdKW0K9DyL zg6dCb80&-PJy;nS(m?4ABncY#1+70}Wnfs%#=u|?T1Uphz;FPRA3<#msQWXR85kCT z#<-EpUC+qCuog5%$jAUXGKAp=BLhPsD+72>b`@QT*aKQ40&1(WGcaU<)~7HqFyt~aFdS!PU|7$S-vRaQnHd-kfabv&7#Jc!V~U{lT%fg63=9ktLF=$U zdZF$BdFu}&149d_E@xq2Fl1q1m;g1)l97Qy2eiHhv~~>?77D5<3d#97rMYmG6jU`53kq^FlM_oa z^Yb)|71Huc^HTH(>IEspqd7A#CAC5`MIk>;K~`UPZ;os*3V+QZ7`Y zc4kg~Qe{bMF@&3&nw|*ddMIS%mlhQ(B<7_ksQN18X6BWGl|jXIkOU!Wf)$EWlk@XZ ziWyW>6i~xAB{eOvG^YePoFQRKNFgXtVJboH0vQdW!FIsoUZEsEUm+(yFC8Qe7cE8= zhNM4uN(7q#3JFO3f^>p-Pz%A_{GwbK4OX3znwXLau>{Hl3xi?{qz**G1rVl!g%RAG z#JrT;#G-7F4j3D(D>t>cI59m{j|(INRWG3e1gM%Mk46L^_uPn1Tvm`Y|Aty5r>~&NTu%fcWoKmm_U*uc2|Pn9B$kvEWhRxDq%t_BlqKdRrz+%RmZd5brKV@*=P4BA=VX?o=A{;c zihz<5uxU9tAZNvc+*Qor2;qS_3gsE8c?yYn@s$dy#R{0N%*jDE8*Cz|q{vT8V{ptV zQE)E;QSm-tGKj%3r#!K;SfRKeH8C6E+~NXIiY(4ZO)XIP%P$4FJ3cMH zD7RQ4r4;08g}lVF%ye+silHJiPa!z5Qo%7N2T3X?v$zDm=7Pk$)EuIeV6^~}p7A;l zssx+%q@4WZ?D)dc{E}3>PC!wI&7kDeoE(LCP{EQ~gz!G7h=>QJ54?sWslsM-PG&qP z46#XpQ$}TeX^}#FQfW#`W@@oQVo|C>No4^zN#*62WPs{Nl-jbOC_fpL@IdK22Ndg- z3Pq)Pd6{|X;QF&9BNLQ_ii1(?C*nI#zti3)kCjDGDVSsS3&Yc_pcNCB+J*d7z3r zEhn)=p(wR1GqoIK8dyb6W93QIi6iAAX;C@CC| z;=Dvq89}V-;*z4$BcI2dZd`;R2p{DWLXPei4IH5xCSTNKH-7P{_;!MQBER zXuIX^ckUm+>K z0u;qbsS2qT1&Mi}gyak=x>So9z;tmzVqP(#nU7TvU1?E%Ihs09v@tkmfGQG&;)49_ z)I5c}(%d9aSp@PqgL6)5ViCARNU6+A%*{-OCME?)0a}bjK~a7=LKfT_1l5M{X0|h2 zs5B2vuo$GUB%>(5G(7{vBp{7Ne^F|FQA%o2Y6^pMer|4J9*E8>Nv#0qN>Iq<=aqo^ zF`%kFJ_M8otr(m^V);1=7=?;+enBSgQVl8#aU;k)P#!@Pdd~R;mEdqAr6hIEFU?6& z03}aw!zQsL6>LOtD!AoQtdN_SmzbVfq^ICokqK&x=rJI4q-Ex%D8P~sEDz~1I72H0 zXh$Ik+!14NE-A`ka4sz>&M#63fE6B4eo%fX$ZQ7Z(h>!5VFhOSWag!U88|&$nVbW0 zZc1uWX*#rj1gbVl^At)lb5j|dAu960e#!$yN-~zrhDBL+YNbMIaz;MHOe_lE0aO5K z0Af=DYDR%d>-;o@g3`R?l2S+p2Y25XoU1_P9IPgC@eE>ci7zdJsL&`*O)l27VsJ?; ziBAR9yt#=bRtzqw$wjG&#SkACL(0j5%#!2`tTIK3C8<~?%0RgRBn9rcF}OfGaKV*% zB^jy3nN_JpaIvJ)l9K#9P>HHq%;1s=>9m6q9;oF8sTx#M6iQNya`DR+Gq_|HgOa{N zJgBzMPXjgPQx%FUbCdFOKyn2+iIob$&@=}ZNK^pZlb@ylZel@NV%TKC&IDTmHVC0F zIU_YW8&s~PVwKIwOwI;53#%loNW`i&HLs*76RQlUMXZpPnVOS=%~VhsmYJ81Pf8)N z1d{3$R8z2cHZwOd9jnElmLj-0iA7URVo`dkLVi+KYH|rSyFq<7?Bc~G(2kW$W-(ge zf+7c-rh>$x#Pp)Xf(&euMTsey`3jJPg-ssP9>?MZ^ll}ldr-TOFnLflhcxP=P*9Yb zmI|uhQ;R`O&a}*QSgwQibdfa@R-6whJ7FCnM57zC&8^4a0#RL1lwX#ak_zh5l_(VD z=jVbNcFCD(naK*!(E){w%;J)KPzr-NPb*4~I0U-2oaZ168S@^anKq#090@)FMm+kmO*xAwzKG)aqKbkvf`_zlOY1SXf?J9T(59kEmA;HhUhz^iX&GXC>n}VLA`yjXVMaj z!Q-3diA5<2NL@jwN8-T)KXCi8cQ@c_v2{kU843={@}k57n8At3@t_U?it|ApS4gT< zh=+wYOfg&nWDL4sazBz;xxs zm*%DxWhSFIDK9@y7Zf0%ia9_g32H|hzzcI z;GtiT-HDlbsYRd!1Qr4Jw4k!!VvWHyuOzhy9A&8$nI#IyU0hIK6DkkNpm|_V=_x1# z6oLBVsl~~O1*xFMIanh?1w;$TFGz-gTu_n<9+E+*gqxL^R|)bf$gm7hOB*!41xvbm z3JM|l3Xnc`MydizkLFRs%wh%DASJk+q5~>Si;ET94D~?T(o;(m5LGXz+{L0F+S-5( z%NN7VFe2IvxL#1p2;8zuhW6u-%6YiC#$a>Nf(<4MawIftAtgvrQGSt?0-}ivYH^i- z#^;JlKx4Gf8dQ$~+8S0s3SWd+W^oCqRsa>~;BbPK>X4qO9)p{wk1K;)YAQIDl;&mU z<(KCvfLdMF$*BsZ#i`(c0NcsnRs1KtoG#fuhXx3{;U4P)`>+H0z!Z$_LO!DLe~<3@XW2 z0CyM=O-~e2*iZ?q+k+wrZjU01z-KN{1)+^o6hT;<6h#o$7DW~WH9;$p1rRMyWKmG9 zotc-8MF^##2?+?WkHIZWWc9F?C8`*rMTsH~>a-yl25MQN$`_ZQ^T91lR6+P~II=Lj zVTmk=+@M4jFHQw1FUc=L7K9YTNX|oTRU#`bL!O{O(gCipAp8Q*@ML~zF;e#gY63zA zM>;_$Ku#-gQS|hJB!QY{5E5wV1|fl#cHk1o=?5-|k%r(hsObn@7)x4$D?v_Aa6z;* zg(QxVt`KsFw1q5|jUMQrjtMp~k@e;gXRK3 z^Ir^}d7x$pwt*jPGT?z9Y!c9cAJ4qv)S?mwPtcGvyaG04@J_9Sjm{&pi@}^EP}t<9 zE2O06q?V+n=)sz$;PxzN6f!?AEwdNGx)fM zx%z;HJbXYY2h^v8S;pX#SW*Ux30Qzbbb#9`dJI0PiA8u@%U~sCpeC|v3Q|dpL%0}4 z98{8E2p}mzX>^0fD?x;UOMZDC1DFM#76G$@KM%$(E|G-1%n zqs(H^G$Vs=YDuCIgKuVDW^QS&LQZO4dPxSTu*gj;Nd`5dK`ypp@Xag+PoJcwfE@u! z(hR=&;E+X`SZDCfFD*`mkP7)_sYTGiHc&qRvO+`;DhX;cq?RkBKn6rp(1hW$RKEFT zsS5G1<}Cw+3n{!H9HgWNYQlm76D7<+0^srzTyTT+6Qc!QnBvz4sWfsxlYY32hDI&O z9eB+Gse{iZ;xa5FKQ~o@penF`5p5@2hJlrV@|Qw>5ja|LhA2EV2pbAlN|eFi6rGp^ zieyj#!8))YVVsTuNh&0z=H!=yt7v|lP{^#G_5SBy4^?3Y>&$(SXHNuU8h z5FZ>Q8Hu2oT+nKj6wu6~U%moTcU=J_3m#O_WAMvY02M{h^;!@<$Y&r4kd2^0Zdji3 z%U8(FFG@u!*Ned#AcEkwHIe|*bO1tCGOXo{tPs{{PDK&~HJCGz1rUv8BvsIMaxrp? z7-1Pq79j#|9V6*S8LCGp1GOfQRe|acP_Uwjp>W|1TO?6)Z)F6`sDUc}|Xs|K(7o_HaOA63X5o{eFWU$D+D8ICT zB^b0YK*1R_N5%jVPs~wBEJ_D2Lo9|06!3l~my3IT@E2qXTvvXh62K0L%op7EAJ>D>oGq^T4SZ zW*}U5Nq%~IPAXWq3=~Ts6Y|p(@*zXI0Y#a4CEx@E8JC8w|3k`lpcsX$6HEjx{{XG% zD1xlu08K0~K$paVmeV9c7ZIjbfR=jdae)@TWagEoLYAh1N>Wh3fn`A)XiWfFSpZs% zkP2QYm<(PlRBR77IT^laB`H+_vg8fiGKbj=nuY|ehX)5HczrI|$?4#^6sN=@g;40q zxPYR3h+tA;k%DRpC`=#%PKiY|e8k=X6mhqr)WXu#yyQv+*t!jvu^?UH z;FZH54SA(`$(i5@0aTuXOJ*`?1V6E;5+s3ZY8W>Ag_s-0ry4p{hES}>5CEE=gswsH z0c|Bf5dp7Cflag~f)nw77KwB zAAF5;u|i^TaXu*EKz%UK@=;Kdfn`HbFAY>VLZ=IZQgcB~YLxzK5M))V0ywRL)-L8C z7PV&P6_gpyHe%D8C%Ebtb=DGerlsR1UOb2DB+hGer*~4_dYh-E;z04_ajlYh-~{zz17E z(wX2PqSO>n8x~|AsEY;;p;X8?AH-0YDliY{Lb{;*a&$SQRdirk#1gvTcyOJUoS&0l z1d4bC&?<*whTz1qR0UY(cEsQ-IOpf3%hhS}~xk zPg4Lll3XC09Z+Qg5GzK|^dQNAOKa6)GzIa#u*rV!)JhG|k}jyxptaSYL4ve2J(w1l zP#(Gne5qMcDx|DKS5TH(1X_^|8g63+2aLEl3 z1TCIGjFTe7;E59|$kGH1}@j1+JW6r`>sH7_}pAvm=Jz99uUyCUt?fE0lx`QXtu zkb01L&~-2+`QUle#9{^5l2*|8Ca5o%S_Fz9NJ$71!&C`10$Fis0mwMe2pwW6lZJb! zrvfw~XoB5~RTa3rL@3M1Oeq64Zb6?~wJrr{zC!P%Jw3h_xfiFw)J>DOY0;QaX9REFS!#608{V{k!gVth7i zge*5NH8(#mGr5=nB%Tc+72-j22gq!NW2l0=wN(5}0@5^yaG z_5o<;4Wf4j)t3t&)zbwJs(?nflM_L6g)jxBIVG6|Ign{(1@O9Om<6EP4bBFyTLu?Y zDVgb+pdbR5U!c(!Sbr!Hv`C^X6EsbTSiA+TouTGHLJZW#hK2z+^q`WE#$iD`Y{@Ld zh0uXf*m4Z0TBs;!VNia#0!CLAsw%BCCkM0*0Mz}B2PGSDZx?1YiY&~0NU@JiNpV3u zsNe$c4uZ*p#wrvb9UYhu)WgN#@hGS}azTNd3|i0%DP6$fSe{=Lp90ebSr-l#hlH;l zR4bAMC<2RN;?T+#vV$ZyKOQtD3kk5I)Z)?{#BQT_aNij!m0u1u7I~)=DE(ncbKqPJ zU2cNhe?)Z0Aco>n2dc8+Juv)AK?wrtFkGfV{EI~qq;Aj5&qIUy4f0ZIat2FSYEcp>t5ib9DyksxtP+t#InT99FUj52@|BO7`nVVzACi{Y#3-u z7^D*n8HR~3E=^Ad4YNYxjMz>*L^H0)fF>dECJRvCE48A8AsD=s2sBb+1!3!!7Qh-; zU=e5{K}=mR1Y=zk2wIK^s_pdf%7dCSr3I-)48i58DJZo-IcV)Vd~*-dT03yT4Q?WX zN5U9_QB^{BSAhyyNasNpR04rkrlRlB3I@j=Lx_iekRL-xkgKZ#e3lWs6GH)MP%8wq zI{>~Rte64JNAyADtk0B%@6=eiF6TF_dq$ocp2b6%pQ37%hL}gljPELL~NCLD8 z547K+EHNiD#YzEe4tS9$sD+=J0!l!zZgUc7e>!M{K(!dA3^o%B8h%RxZHg)acX?7E zwt)84fy{!osz6SJ1QBdIJRV18=B9!J-UYOAAS55M(G|2GqyXG)E&}&x^cXN@ia{HU z!4k>&IXQ_1#i_96b;Y3eg+f72DQNF{S_xQ93Tzhx#8~jiTw+mCez^|FqnWU&Zip;o zAPy`IUdERWUapl3owS3f0Zk1-hC)Ei(%i%f@Pr;jE)}%BKO`Tz`3relA4DEBfC-ic zt;;MfO;X5B%`1hu9@%n`w;`LNV6sSl11ki34zvUkI`9c8H^2rKgPH)v#gKk2Xbi{@ zG)@B60Pe1qYKuWtMoDEsszM^DA*fIcZsmiU(;@k= zU4!so2Zw2XkpkFV3W(5ySO(qf1geN&4g<|A7D3k1K~yt@fX9dwkQUg&gdp=r&{@pf z{FGFf1awCVq(sduffm4US)4@(Oa&;z6ldn7<|Tu2Nq!n==*6wn6AJO$9!TFh1c zShRt55oA_?hAE)S{o$=4@YFuYIGv{i6Lmj5DHnDUy`o?%4o@nImx9tpk_O$Rt8Nv zFofoTi%f=4Xlq5am?5+PbdEw|aVkS7=nw`g1%}Y#RE1E;h$(2HhJqtFmx0!MLZ&z% zLoT2Z9oRY-SCr+~dQcN|!0SA86g)t4)A>aTprzi(rho!01G08lj|((VT&#d*5L7f6 zRDeR#DCqnXZ~_I7b3@Y!xbTJ<0b1+|ZVW>-B&H}Nf^rJV_7OcUuoDw=N>YnJ9VP`x zUq8R75o&szaC#dj(?U#b=kW$DmNX^sZ3V^HzO3ukIP6h39PD)J!&BTKwK?OL{ zCV#MPpbh0opxqkq)CErG;9aMwu*F7t3Z7{SmHDMyU`K&VYw(gl=nMcTS%6P8Kys80 z$e2on^30qZuB23jl%o8C0?5cEY&HQjXr{-7n0o;6K`w;Jr(_lN)D+MFI%uT?8K zD~5Pb@d}#DDlW~oV5N|jUr|z&U!tRsu3)8*o}ZJZ zqmZFsrI3+dlA5EVkf~q=>bPen>L_F>SSe(c=47Up=qO|>Sb-0h(ox7!uu{m$%uUo$ z$W^dX$j!`7)ltY(uu{m&FG~gO=+{xmSFlpZ2W2lEg#raDg@VL_L>+}f1uKQZ($u8X zWF3Vf1uKQ3{M^)h9fe{AD~00B)S{w99fcAFD}|E8y!3n>g;E781?b`r9fdLlD}}Pm z@iOBfPMOY#{&1NOzBtvL`Ds7b&8UeL#ol#`g84O+jEo1d2glFRpry{mEb*Y7mkdco;9&#M z&`?rI9z#-TPEKkGL$X40YD#8KP9j5cVh#hg-SjM=mCM*=z~*Ar10Ke}t_gGm26h?n zP%KvCz-u-^nu--bhxjmn4_aVIPReJ1yFN81heZ`>S`0Ma2NJ+`7z7qM#7F=GOcq5b zucVj(vfK=`Tn)lZ%CBGni>0O@1VBRp7=i_$yOr3gfUyY499sECSaXEQvXp z$)FW>rKu>Qc_o>JrJ(*&W(lf9VQFG+Vi9PU0eBt{YDiUS5sI>;)Xa2Lfz0AUR4c#< zAK6aOKsk7EZek8NFCdwp1Ug|1jjvFanGa60py@=2GeDzED4t6yEy}4Z&(DYW8|vfa z#FW$$1#}}pBby~fsh}}sB#V+W@{{vHH88S6lk-7a+>lk}7v-hp%wVH%rXlvkXY zlZ~RkC^NShH5QU96Hy$V0$O>E?nJO4R+Z`bIVq`mMX3G+D^D*qS_LB$!m(qeELz%aNt z6;z^Qb9^xItCBfu^_?X>`F|V zGjl<84{F%wr=(*^B59yS@JU6P$tZ~=EeDj!Kvf`W1_U+3i%S$R0zR!YIioleC7#j~ zGxLg*@{973!!bQ0zqka`SWpT=QHCu=p@$)cBftU*m8qc7P-N3UYuGANQp-`rN-%;G zG*y?Fr+}6sK%(g=p2#fAFG2}gjI^7RSe6PpX$;v$m>4LsiZf7U%JVRTGzT{T-Q8++_(K0wh6cp;IpnQuZ%%CdJ@-IvjEe}A1(NiZx6f-YD z#j#~3s1%kI4V3}sGxUT2l`Bb2&A|~Ym}w#hbc7F5Rs!*{#6e~rYEgxyJjzWh%14c$ z+|(4%0ceR>D=VlZdg%%k#w?_u5(TA21vw}Y4wWdz7LG7EaB$(Us<;5uD#i3OR4>-T z2`UFEp3pN&Ze~gz)})yWTJ;CoW|oVb>T@%TODYwLKqD$h@sOLJoSaykiBdm+ro6K9 zF-wiS#4?m@n4goP06HWP*%oj`fgzxfQk0m4B8pLGM6|++GgI^OP%5J0%$%}Ra4R$)+6Kc`WkTv{^gw`!q8B*DdHE=n39hVEjI~HA zL2Yc6q=Gs-2oHb;VoFf6I{4^Flqv{o0)nI+)-Ll;-9sU_Xc&WFJ@-)Y!_+1;qvU@H&>F)D(~>Ae_=XFb8y!P6-Qm5f*5L zR%#wd6Ph4+4>AL28X+~Wge4<0Jp)qWBP<qN;{0Bt$nFA&RORF;A`lF}$D>JTT3W zTu_q7kX)Jsn!U*{QOHkYfXwnFS1J@|rspxFB&MgQ7BQqG7H2S|B$hCwq=FhF#SCDN zr7}RqVL-c3ia`68QZf@$i&Bd-iy2Zf)4(T2l_-D?I%Y`8EMQ2<1g+9dQAny}NXbcO zfG?AQ3}&Z7M{ScKr`;8R)+2zHVqhu*jfLV;gy>E}#(;5}hNKXyc{w?WMGPtVB@8L~ zrAeSQO`r`=Fb*tGAX1>cW#D7hVA2IepgI_|u$&>KD6yO&6*`WRiad^z3Tnrer81-{ zKnG1yQ!>G8iWK1IN-`h`fm04cYD!5`5kqQj5<_ZkK}jV;YMuf(WQP%li&s5 z*{L9T@K#WaFa#+BHILyEh~QvIEi6sUDP{mKvtUUtN(7A!LV1~a;Q4n{9%$^Os1i*K zt3J?_3wWL%su(=rkeQdx069&DA+;ofA+@w9pCPp(IVUkQmjN<)oSMP_I;;tFNKhKM z2M%h(XXY`as1hCYfnFmVzAQ8|&WNA(! zSQc~wy8`lRyNr~)bOzA4K}Kp~S)~GaltKYK(g9jS$NMc$fzs;9e52LjLL+j#!TeYmQUCo>VvID%3 zoy9Sy1i=B1{O9K&1cE{9KNxb7au{+_6U#tzE{M}~^x$I9q=ygyr91==JP`|53_cMY zAqg&KkhqYse2_p|2?J!}G6%{?DgvE@4;BM4vs0nspgOB4ALPU|(47_FA~G>A9o!O1 zOol6i7M_sO5o}6sYDpr*j)KIZ)I10iyetID%mkZ)q@x(T5DKgrbOb+ma};Qa7JO70 zvIYY@$%kItqpAZd0hbG)i9h%{Z2X!^Knr1@brX?VN(-=8K48}%N?JnhMpB8##B2ue z%2Cid#Z(sf&QfGS=&n)*P?`Yc6Bf|uDXh|E0FO68PSGz$K1LtBG`m;YUkxePg#MJWY&47rKPMfo7ABts!J4>Vs|T9nG-3TCB(+7RFs@VSX7(utr`OBpZ( zK|{bfshHxR8X7c3ke;8Hm;+v|pN&NoazR^Cl!;9VIARka3(_I;$(WWQs{zf^VYm{k z0JL)xwEO{dMgU$Fkk%Wfl6=sCBblHm&j%fkmW~mGi3)l7MI{-jpe=#mbxW8|Eyzd& zZBGN|XG~ep#%Itp28P|>nKe+{XR#Feln0t@H_3WyNo%wCp)qEub@H9S~kKnG)h zujoORQ-C%nz{Wug!YYl`V7O**p@&B|c(FE$d?n~uV9;C)sHLL-nG^$u3*^9HxC~e) zD6K(Vg{lu8O&BUbv*zHYA!yzi*awO zIlDZw7;?t}XxSKOH&;4niU7s-f`X#_#N>=r$V$PS%-qZpRI@+|Dl&5uOHy+xL1*ZK zm*^&f4weSp5dd*Ex{FZske~#%9uCrI%1=XeNinE#1M1VDc%T?`>SS>?Xn{x(Xk8YX zp32;Ul6>%Cn>m%(!xnmIK8il*>Hnx=;3-k$!VsD?z*9z``~sdILUtTP20A!aoC`_= z&`DHGRoEmz16QiWsICBsr4=P+mz09Lj3@?y9VF0v|qFgc@L=Ibj7@8xOR`1H}_4 zvS?{5B{ioc5faJhcBNz{f(j+<*%LO#1e$1v+;)QEBFK0XYO(=|6@$hKFe^y76lM}n z$xkf?R~yjiRY)vWz?!Z1i(OkmQEGB3 zE`3l*0ycvVWXEA~acOdLYAUpS1ucx>u7XP9G95J;g04iwEXP2iSW7981V-VOl3xPq zG@@4<(7q|wVh2gCs5lk8;TJ6&!98A38!i>y!B81c;}E-CX&!nT0BRjd-iC^S+xZHh zeeuO5nXpa_JV?QI!L?zu*&t@t|6z0=xwQwA>c0 z2?{Pqz{6LdBdv0BQghG?T!;$LY0s6Q&D)uIkPE9&Vgocl3>rbnF9OY)fJQ_?_mx3= zn$WZfHz&VH0i63vG7@pCfR;FDp@?J;w9vq!0JKss2R2fGusjpAFg6EtClYE$B(<|wVB;X3bOWa`Li{dg2B{;ka9mmFuHDn2RUkSTakfCs}5y&cu zun}IR_xY}A+6cJ-P&IE~S9_Tnq!afJL+CbAp$cZ5%wJ0~U1a#V3a(-S` zX*y^>U~XbbQ6_X;1e!`S@^eAkK}s@{Q6dqkDTlS>%s9O8NN*}?xtW;)+QkmKkO3`G zW9^8-1VQ1SNVuyD-d>2&($36F0~HRHC~n7EnSun1k`qBoHZT-ptzF?`{5gqLl?uVA znm{M;V)PEdqr>3wD$q_W@c1)wgg~T0dv#FELI`88>cH~JshOayshApZ)`4JcX*v05 ztz57$v@r-7!BQwr&CP`DG6H3Kj5at}2c!W2u8=X^0FlJ+5@IaDsEDy=OSmX zL$E5tku?!&VVMn-Dv`4ynyC5Nlz8t49PA zM@uESsfop)bD$N#sTsv0xKt8qrpwJt0k!;)8zoo^4$O8mSOgT37;R>V3}jh9a!vy6 zUClwQ=W_G&^1-{A(Hoe#rO6q%8wg-oc=)1v6m-T#ZejtZAZRlQigQ3JK?j$CkHsi} zUtfw<4Q9I=v@kI@$mnSV|Xs&Ln6J1ZJs? zO#$dE64dwx>BXAe!P7CB(D@Jaks7ch)=|*n#JpnN;?$zdH1sAJk_>47BOz(*Q*lU! z;7|ab6vr?;wL}5jtVHpAab{ksLOEzNDRMf8Of^DB+i_3kpeX~VTTnwCeW(qaI+T`N zVhLzjEU2}G)cXc)I)$xNfY#IygK*Sz=#r38NZjs07z0sBo{REJK}%rJR&&6di;%>b z%ZkBjzzqxBY6>!-CrMxyEYRvG8Lhbv6D~z<#Y2T*6&-3)0B_GFTnVC?0jhLCRT|bD z1XBw-CJNg?K2#o8?T0B1vJIb2NG5@l5^`8kKH9`D)JDv{3Pb|b5h=kw8wOK=C69pv zHU)g96qXQA0bl!#T8)5K$ziKrz~a~o9njci31p1|j#?Lc;}b3l3NP$ITbcyw!m4$w+ffKStb&lg8=3q%1}95sl+5}*x~sLC-~FD3Z};I;>9 z%d?~id}t_Wln~QR5IM{?EL0OpkqNGBaZHt!ptpB1GZ%<&P24^Wf|9f#5|9E9RRT0Ck%4tEwF0egUj>@bha7pE zl$Z`(DpH)039YZdYouB7QbF7QAqTmFS_lx!AaY<5O%RfNR8zo5p@F>uQ3Y<9K!l4K zK*!~Q2~d$#0-CzY1n(gOr@G9%(qab0QM(Med8HtnR0JYH>tjJ9a07ANpER}3g(A^8Oid7vA^@{_YcjHJ{eD5X$bQkj#=0zRCp7*!0k)V`PjbfzNc z5R!c4?F#wO?F#vzRlA@iHTh6K=fn0dKn{6TD1w}051PFIpX`#D4B8a|TB4kv$B>V6 zqZjDBFv$EJ1BjWCn3Ki;I-{u=v`Q`~KOM?RFUm}TGC_;0lkzK|Ja804G?WyjrZVIg zl;joUF+k2@&S5A3-3@rG*y6j(7_36{-DUO2}40TsBch^Ucvw_$Uy|CUWK%o3i5IoFb*eIEoLalF92o30?>l@Vg|_W zF61lb!As?#2f!4Rr!c^}{0xv?44?(m`3zt(34FO0>H>UZ30P<`6s6?mm4dQ6Xk|WV zg=lID1L(#K(7|pDkW)n&!1W!31l^JXWkHrfg5|)KEod(Wga_(Qf%a@bc(7^&wD=ZH zAyf+LdhpI?@U{(zM##Pm2ph6-1Ik9;xd9adwQ3kZ9aRRWNX<*htbp*667%v>i=gbxq@2ura1yG-6oKwe z16!Y*kyrrA{t!-nPJTf~ejY>%Vmj3xz*S9DQm1Y-z; zf)OpIG1S1K99;q&$yf!8(L@nR08Ij#7SPqh(gC_^Xo5f&2B!>kK}Zro69uIebRlq} zK^KIk9yDQCGC~surzZ?Cc*4SvL8LG=soccOJn*@Fsd*)6QhAW0MKkmB&?LZ>8K}m^ z5HCVE19a$NVsa|F!lHa|HbWOK&B+0mdT8RHLKwplkmH2WR3i3Sqe(#8f#CCG!CQG@ z(U0tXNKQle8o~#A7Tg9y;)6U7;}(@bSw*R!-W`ks@gbB4^B9B+@ehOz@dlJ#ngl-D z9>#;8tqv{}pp8y28^b#cppgu4YZ%PPPlE`6#tT5s1KqX*PBNOH!*LZc2D^4!SV}OnBfChQNtHv3MQwxepiWs0rJR;vb3tGIE2-%HMmWoROsF8?6FQk!x zOJh-KN-6`mW`sH~BfqEwdO$D>=rmAXKWI>sUn-jj<( zJUBl$l>ySJ1FxC`%~FEW4+CglAt>JAS1};%KLl+j%S#9KPnOGC@99I0^EedD~U_1b0XxnIP7i%Un!~JlwX0vY`Ar2`;ISJvyM41a@z_=9Ls>;?(b!UzDrhmYJH9g3FB_ zsfj6|GXt=j4wWUK8GO$y_%=7t-Ram(@&uiTgd-rqa=7g9NlZ%3!J*M7F)szY;UBx5 zFlpRI7p12vK<+!msRn#W9S-v|^RjWdEHf_~r;(Y(B{;Pemne9aq~;Qm$7eP!Im9kw z?B0O{1P+@65}{pCLh`t54@ykQ%vW&2m)((-;4~&bCl!YiAQy9`rr-;};1bZ$!`S@~ zzK#Qzy`ZZ&aM&9fQD@S;jc9~R*vNdF(f2aO9L z>4EfSVVXdr?GTTEJcZzayoKO_Jci(byoTU`JcrcpQ=i+*E=x^B6# zRVqj(Clx+M3b~|B2Q*fy0B*}DKow(ES4>zTXe$fEVwCY#3?cZ9kN9jY$}ca*rx1LA zEodqVK4wz_8d@qz%3&x;0-a}2l3J9@0J=Jkr6?soFQ*d9PEAZvKyVS7Q!7eX5JOsE z#h{CH;75vpOaco)t2l%TP)=7!%1?pV09FG!7a6ptF)sylxn+J4LNSsI_|mcr@WJ_5 z<%>%)3qVKn!EH`TEKUUv3L`{7TZ)l1gN~v=;zCA(5vogcbC8`rO#YighASe7F6jXq& z2}ZUjwW6d5eB(K~10WLcLyF)=q$TDQry{IKOU%v8sRSP{gd~`mgXH(L{Jau{)U>qJ z4iB~Xh>kkVsua$*ir5Q6&DpfMWs3;-6#O#hJ1EW%}=JHe57;9~@m z6AO^MS)8AfiIlV92ZO;KUR+X?T9TZBWD58w76ptngck0_rAX-pTpJ>cKu%I6Nhn2A zNfJuY1agK#N-F3KTF{--NJfC}KP$?IT%Cy~T%3`Zf}Eg1hUh|1hXJv{1vQAF3px%4 z#DIw8BSkTI+8QoZnuDVtf=FOS1b6`gC`BQhRt7p^1-X2HPyHt5fX@4aTUL%%F@Oh_ z5wiJ3Dc}h;gvp@93AuU>p{ghobgu_gG(87&Bz{Roeo-DnNk&m>DyYX^RFYB50GZ#1 z?7J?>EMS0KwhpC`=1jo%kAaG2@I_lt34|bY%A}+yF(nn;%PJ{KWdO~;L9R6f_4P`? z%lJw`8v~&e&d`+v;IrWwpd82)Pe~EDGOs9MD1{!GR*F0aSqhzlELDIW;D-q9(!6Yj z(gFrp(83wugWF)D$cMQh#2`nxA^5O^+(2bEs9mmF3@Sdd8DM;Hjayb;P*lPIofQX< zr|RvtQ(SVrI1llQc!HAub-Y-l9QOE2fx2t-`&sO*Hs^Sxwn31adByCF;{@U zF6hQ?(DaEe=#o4u1tS9^BV9uyT|-L+LrW`Tb8Q1d0|PFf#Nra&kfOvq(7~knMOF%a ziJ%>$3U2v1IjMQY3O0G5%K%gJiXGq<+Ht{dKhX_IP0Y1Ya49WG&QP!cE6~l$LAzfZ zq1;L#FNe$5)7KT@WkWp!@Le~lc_q3bl?AC*;A^||3vv=O^Q^%My*RbRHZ;Ud*8-sq zkUe7Q+L{&_vh3Sl7^8!N9`G*i75Nz`%ejLf0L1Rw3w= z7%PQqN~)T-1X-Qv8|oNUnjLZEGQ z3T65EMGC4KNXIN{7AvHumVujhdPr8_G$J*RupyvEP=#iSLRlhciXS%Cj5yU5MI3xd zi9&iRv@M=ml)`{dCCIrbNscQCqlU%3ZV{~LEV}HNgxU( zsS2PrB1i_DVn7K8A`$``6jR7eEkUGHOd(K$RZUSyN-YL?0d6D6IH(wsJ3ykKp>xpv zIz=cPP(Y<9Wak%@q-GbFfTUn-hz#fqJdh}eE`~8sYy-=nh~#Ew8YS>kw=2O9+FxxJ1I3aCk2$TK@xBd z#686YiJ&u&R8v3;c1l14t*R-Y^-Cb7plj!#bSl^ZUoz6vx>tD2&KOAg}Va!^_YrzQvs95gsg z!XgYZq!@IfD=g821|wm$q=sq=WW^5LW10+@V#S&a2H--Vn8DD1!QS4U!BN4{+1b@E zM8VP1Jru!n_6%|k^>y=cjbLz8a7Bo_2RVj;xX%7T{(g=OjtU{3J}w}EP+uR%&=3aK z)I5dk#Jt4B9EHT39MA={i8-K)<4Y9cVd0&aT#}iZrjS|80J?81wJcR39(-q6YK|3y zYi4?CUQT9Kb}A^J6_+qLRTsi9%vx zUIA#X3#1^i40K6ZYEcU4g2l2_UGO}hLQ-l@YHC_aMrvkCaV9ACA!qbD=H#R*WGBYw zflf!5mb-#ruGYX~Jd(B<7{&kf#i* zwcwJF2m`UI!)l^)CTQ50VBla=hRruzL6<=I} z7O>b9`lf>J}7?F)DrNeZ+Qw;nOS)Zu0@dhp%uV6 z4|IJAa@7bfrHf&y7u-HcNv%p%C{8Ud&P>(g3d>I|Qh3xb2imYz(A9-5Dty#17Zf52 z`MC-yi6x*#r^%pG2*IUaSz=y#YMvg0XI@5rDWn~elB$rFlUSkvx@0i59F%Us?##{s z4M`QHAmwBi&j6iFqI+pj?Ig0xJeb&~cf? z$r%dSIiM0i!H@xZRd;DgUSeV{gJUW9{QXQ&I{{MC>*nUClorGD5%>l$UD*6-Di#ft zsfSG=q~@d|<=KEl(8fju&;@U~i6tP{!E!!4#=#K;jw(=8$ET(if$r`}%}Gp2%~JsN zR7)6q6BDx)(o=IvGgB0jGP4xoLCQ^T4%oQD&ANLs(8?Vs0@akb=Ow z0YODDs0f0Uv#EIs`2|&(km@ZlPa!2$A)_=CRPHE1CgxKaz;hnpdXvE)l*+O}w^D+d zn&5`H9s}%VM<}feZxyHJ!Q^y7r$#4(8u$#Jc?!iPrPC>xaIvq4SKqRezX2B%6;!hl9^A}DcIrIzS1I4d~2x_J8d zxH80hKs^IF<2RMTIWaFWB{j8J!41^SL4*!=aU%wANSJ`qQc*6boGt>_`=FY+2$ZMu zb3vH|9C4ub0H{6$H4{KbXQ$?YeFcijq|&0)#8ObW>oIub=clFQq=L>dFD}W<$^rQ( zuT-G`bdzCvQDQDm73rynIX15rt-#W{(INKII5f}ln$ns`xW7T6dh{Y9Bssd)@8sS3G? zd6}t2;2Jf*Kp{CZD=oFC7@UMt^Fa2erxq6!fmd9B5+bOUV{oa=OUwmji&O=0!a}re z70NSQ0&7X`-;rc^GdGg7Qjk`LM}2aYjSw7wA71gy$1 zjSS1rNzVthM8JLkX#yup(1m*p{sk#TiOCry44}i&K|^er#h^F8aVETmMpvQuG)gbFi7I;KT*$pW#%A zyC}!B0c8H+)u8juLD>TAdC*E0P(DZjb$~$?Q5xtvf=qBh0xFuaQ%j3L$<{kR4_>f9 z^CBc8m4Q07d3p@6JBE>R8iR95Q4WJM_)-j5VFcmn7Uh?MhTs?=WnOk(CTPheLr`jZ zYK{VoM=%WXG7C!d7+gRuPf1NGO^0-Kixoim6m-ooyuv8WEGf$ei7@zq!ZIaQp)5Zq z9aJ$ZWT5Bf^u)wGh%!)+!_}4Kr8hiERX3Gqnf7r@7I zK&>)V`x4W@9qvp}^G*TX5ctRdhD>@lB#ZL%Qn1AYxJU&x=+V6eD!;Jx?XlR5wSx`~jSzTawHQ(0p^hskl*1ETSblyH zq)f!A#4i)Hr5qB~<)9q_kiGz(u7Dn>mt0Vknq8cpTAZAbnVOQC2fAB4wForETT)b- znOl+yDQ*)J^B_4w4^&9yLXv()B8nPFK?3Tm>M;a>23q6Ip|k~8a(J#h~&PQEP+iM5NRTN^ZsArVA+K6pAvlK$96r4FS|@9*c>n3ee00TL-FPT~Wq8 z;5?*p54ad)%)?ayHpCI)!4Lu}x>J)g@)<(G?Nv|<9MloE zpAV{#5n3^o;WVTwGY_X6*j$hW1QqGQuXP7E;)_dCOY=ZyGo+^`6_sX!M+h8q(h`$W z!JU#+PQH2FbSz^7u7^91c_ zht_CVq(f4RO4D^g{stu(u*LbXQ42`IR>0P^jt>S8AcDH55LFEE!6ilDm9i+kG!hhG zwFle+NsLcRDoV`;g)uz4LB_ve9*ReV6Cz<0q!uZ}S7n06q+tP%CJBjibiJUAs!)&` zUj!OPOU+|&%gHP$j)xE0B6%q|IU_MUHK#-&C$TcWv;^F_0(k=zlnR;PK0QOcUukY? zQD!P=R1Tc*k=+9t#47`hP2}b0>4L{(!Og*xRM2o_HfUND)O>@bAO>$}M=cfFq=Hz8 z2or>ST7GhAF}gIkLI+LImn3H9r55QiKmgm-;$&TL1c8S>QWbLGs!LK8l2Q+^26bY=ZJ?4waNiH) z5TvmWJqCpN>8YTRPf$>$=qbQ00kw~jZAgP;D{vv4k_pXupy`H;d{Cnqq0!9{GC2ea z==|hT@HU^4%v6ZRRODeFgpb^eAbLQSf@@T`YFML80o05Gy9YG+gwfGOGRl}VqaZD6 zczeGDUPB^`gxrmW5z>iiAnzCFlxCKIdJS&*r6pDhpuPjB^Q(aH2E56Un3$KFm<>{k z2z>BJi9%vpdTMb_KG+;ca}G35gV?{DipU{w`)lf zE0dzBac4`hbv0{d(e2`8sm0tj!vhdCU^&UWaAtO4V^rKp=$ABgd z8eRj{ilB)_XvCy}vNYVi3~r#@0vYu{W`i2gh_MlONbwGib+7{zz^D0wdT(fBA1GWS zhOorq5@;dmn3JBG3%Wem1ys_)dJqN-C|pBSt`P%7S6-?@aYL$#(VfI0{eo$iT{xlq)OA2=1D*oM+| zfM`XL&j$A$5{qDc2W(2KVh*O9LV8g?=q`{X&}t2cG%OU6d)eS#9jL)tgy?z0hZ!N-kV6nO4+NT-#&9U4 z1OfFruxo-(9%1NAReK`*z1 z_L?E?gGL<45qJ|mSOL~#50b%%Q;;A=k_S5q)&W7c9w{r}OzvOrJ$n3C>H+fwr<4klEm_Gg1bJjF-SW3$CD!FsOkH?tPSj?r{Lmy@IuYW;ycnN}%(x z#OX=RO9G$Nk^fo2a-1i?iZWMmnp4lD#}3#S%=&fCw^V{k(B z$G{Cdlztev7Y>~b$j{A5OiYJzz*8FFmL;+Pq(KQ4$WWWq~Z)M1z663}E@X=VwslEk!(#5_pEfTk7`OF%={_!WRMU_eoRT4rjF z0=PfH0B!N77J=s0ki?x*t1>}HL4o@HDXDpS3a;QBoSIUalcJEAQ(RJ-l#`j7R-(rc z@0$ub8j8U;u_!wgbifH{bO5@?8#31d&c~pR3#bSJuSA2jWn3i_buIgSKo#hc8u&8Jr*zsgMN_;Q3?FU`T3a3X)WOQch+T z$b+DO&SUURElD(D@XgH2%q`8$NzDV#W`GXbFH0>-P0h>B&jrupfW2bH5SCh$otj#d z0$RCK0Gd+;y9s}6hPDJkWp7i znF;B%>VXx3&d&tNLkD3HK0a+60Ik-h$z<+ zQU0a`251zt95n8clB$qfnpq6V6%dytK{HA|Xw;{uG(8(J$C{Ly z7Y`mAKz1v*tB@2AZh)YOLsusHIr_SSvT#XaHfZ#<7&^_Wn!@0hngXgi@=}oMWxveS z(sJ+wiEc?^5@-+sJXesK2gT%_9%MZd#2iFd0lrQgtQRyG0V-E=Q$b^%U?I>L185QwNeEW#Lgycm zWFWmLl&ME#Sy&fJy;uQBI5Q74!wu>%ftRhoZN?^2l#*J6=q!O(5Fw@(q5dobEyqMr z1(iT_o=`19n@U7-8n_feb}P6wpbN?oC|&>yqZ*26Hlz9$x}hx%RW(v?2gP8to(_r} zxRV2#T|{y)t{x7mZCH9Ys0y$RRYFn@bWs4P8IGECkXN^Wd*7f5IM95eZfRa7XjwUf zUw(cOJP#P4at%?rMyOn429QCZnh%r-Kxc`8N7M9Bgu%f970NGA0I7tuC_#&+^-yZ2 zOwitf)Dq|lMLh<;{1WJ9##9D>SbHA4P#MlcYTd)dAgz0U1s8w+AP+}J9|nJDVc-vI z@cRdZc)Bt`PE`O;4d{WF{enX;9yGR>nGUORkk`#ZSAQr}<)>zY2J=&4x*(Ie;HC~} z#-$kCR)el%V*ri%!WKV+PD)J8V+bw)9Y30vUJME|(2N*^Kls2D(8N<>Q95`uKQ#|5 zm|ASb09hvpU;G2*D}YNE1<-IYbe$d88Hr_}C5DMb;N4TjpoxIeOwhUptZE?bT!bRf zS|xDfCm*^n3DkrG&4j>e3&g-ZXxBh0XcYyhu>)$GDuAj5_#)4A(0P>EC7_|~%xv(I z4N#^99aC7ESqv(?6!HteI$$OvHP<2KEMkd`cMjADuye^X1F_l!RQ2d4rRM2oX6q)U zmZuhhDh7}TK*b$+d3j1|Nh0VlMNokSUa*EwIb=B@%8FM=J)V}I2bn*GE$U>zq7+nQ zflgzGRIdmv;EkcFc~C8=3u+(etr%-R~s?}E;nOShV;z6krv=|N4s0S_H0u?c7$f+O&v@i%m6tpOv0oHTGEUFYh z`xn7m-{GrlK;0uug`lAk@Y)&B$_UVCRto6UBUniQo%293%^fskT#^c!1BMPrf_s3V z1PM!Ckd`*mvJ2EzZjj0j60*qd1WyJ!=9Fl=nSnaq;7Li)d{jAT{UNB32RDd8OZY$| z6X}o@V9?xNtj7S>4oc{d*|Ln%oB};AxF~qKG!5tN(gBBA``xN3gR>HXa=aT08hPvHd}&wo2tc-O-_lR zi*@w4!ZUM96iO99D+59C3N98vk(88~1i>dPn}dx4r4`ts+R}2+ z;Tl<0po?MBQ}gWM_GRaTn`)qK7T^xB0%+ndH4ofdgY}G2R$G8dPpCv{9s?-Bfmco! zCne@&>y{RzB!YIVp$aRgra-C-&@vEcdzQfsbY>~&YQj_n(Be5zJ2_7i)OiGjQxRfG z2!f>x&hnrUnAB{Bcz8b+-*O$qG`Txyu`GebJ#f|Fu^Gr*1GN3ifV`vv+9XB^7SQG$ z(4-?`DPdk_Sz@UIilSWb$N+{i(B424b)bn_!m3h1J^xfa2Bhtf3W;gZd05EKpkmPZ zm!L*3s9*x68(8Ls6u6+Z*r3fnkfjocArDA%1Jpvz19b&JBV^!a2)GJQ10^ufb_S4{ z;PeG*+d&t0!<2)z9Rwv7fVQoImO6mS#MC_SVteRb3A7!!dJN!2DUgm2wB!M$Uq~sF z2->y?TJ(!Devp`$2ie{O3cEaoyu@tKJ}Af_LSkYbs8y0$gtk`zr2+*P2Jmig5NPF; zMp1sbW{M7E^|S(L(`!y?Zk}d}9s^h!ZBa8+4AfQy4R)l0%M{QiQIG^Y5TTk8T_8}d z2Rj7RUk4W}pspThY#U+?$Uoq|5|~SHX>|~2!8m9z6LtADrmH}074W)h@Dg*7E7C!G zL`oRqy>q}zj6nlg;KNA3>&s!yF=%dA$S(k`anA!Of)^i1VxUDPX*rq6B@F&hh4G0w z#o&Dhkf5#1^D5^ny`{K-0aLY5^ z5wuUF2vmQ8yp);;Ztj8#^8B2V{QS%mJ+MF#Xgf(}Ub+>0Is`tn0!gvpW)`T40nW-r zsj1n;VBcov=azum+ptMP@K6n)zL7#^F}SjT ztrSO^Uw{dLybm7`hYMzacIKq!fEL=9fR<2$myhe_mzETiLia;ML?R<2BXxa!bzNL^ zJv^*@eXW9n_3}$g7=jVH;Kvq28}gu%4zxQWH5nAops`5M;v>l9Q&eUiV#zf4 zL>zk^LCsv~LJsg22JmnNXp3eFVo4_I0!nB*q(mV%KeYr}ohm@nOKKjt905%~p_u_* zX9=5C1$V2!g)%Nvf=fWN-H_EOsYOVOW`ZE^=^eo#z;nyg5}_t0Ig zph(Hg1D(tc>T^MtP&?%$<|XGVfE(lpYtaHMxHL%@x(h@h9%>qc2dEPb--M1=6x{wy zN(ChoaJ_}p1!V}!&&f#zZ+ZjGfo0|?#DkI{crXK$1dyTzQzguHqEr_b#22L|rW9wS zg67tc%>~c9fksJ+AstdgIQW1%a?q3wj%JYa8REl1qs`zEqZ07o7^uku*^UBU9-Ez$ z3c7;~y3q_&@hRlzfv1_WK|3q5;nOYf4y#{jF1}dSV?b5_ZOli2nVg@JstX$209BFDZWOG6jFhrL161HN1Jwv#zz!;pKxqh6 zvKN46`BL*h*|IdV1XPkh${fhPcG&83!a5LhRFEA)3@+ed6-al(N+Br~GzwILCYqiK zN$WYFc4u%wYHD(Zf=ec-FAF;2gCQPbRB>f-Nos1Y6@z~P*cYHQ2i|qB2NyxN9W-nY zZbK%4_d{eSB_fr{e9#O&gD#0DhLE+^>VTs)|qj~J_qhaGvI3LPmyiD=X`11eiV z$4%f)GcXn4o*a1FBXraSRGk-{<} z+X8lQqYzRpK*I>HGNgb5UuqFmo|=k0M-mPj`6wv`ZNWrY#|@j!$OUb#W`L+HQGhB; z1?}ksr7ENjmIC_5>tIOCGK6^e2l+9Cxdw$edV72Nxq}uZfKLTLjDm)M4n5I@p8o(k zGzPl>XzB(u9srpg0kxj=K-*D~1~QXUGg4EFNAwbf&lq1zd*q?F9qZpgsQ{}(DXe_6~bYv#UORyfjY=~ zXi(1(qzuyTMJUALK#=vtrAeSmjX*jeqxA?KkdO(2EH=*11(iA=Wo7xL<=`F#bmIVc zxX=*f3b<>b1s2R;kiYa8{Bt1#1fXHAqEzspH~1VO(4aIZ5VJuWtx7@35;O={l9gHv zP92EmG^iL)19y`U{V(WxO3<_^!r>{Y;5bOlgH8(MrzwDk(!oIm+6M;OeFN5_02>}e zXu&r42pYiyISf?l6@wU{xl*tJ3`mQDz#*TX1_~!g;A30okO*3Nfvg6)B?UCz2q|HT z3qY%`AoT*I_E0azU({im329g@H08cGa$j_@vRlu{&j{(^XM5_R@ z*&3;-4eBg`c0Yg;9;_1wi$l-}8DOu1)<(kj{h^p#4(f0gf%@>NprZwF?k7x4%u51q zHH4fH0iM!lZ~{%vW1J9yA_yA^fzDCsg8EC~{!SYBSRc>?Nogi*2Lkw*5^#@C0lXOw zWnwTC#zUGIgo{BY216B~JNcZ7GE0gTTtVeI(o6|9Q6mON&F415PO;2GBMY zaFaAQF*zeMFI5*YLkHT?S(aLqU6h#xT3P6y2dgj`LLp5#(8>c3#8z@x&(}%;#sXzK z^nw9g;DCc2RBS@m11aR^frs2d8o)E+ph62=kAib7VyR$pa$*6vEJoXN11l3k3v?7* z^2_sd6d;9m8mv@CE<#YP(&K{FO0GCehbu@)g`VUEY4hfS#}vV9kig3w!O0Kg@{H7? zjKmz!(PJ>9!Tn0`ffArX7sM+r01uX=W-CB51xO>fsi?;VI*ci`C=YacSQ+S8iUI}b z7zcRND!&NMMIMO27wGxmnzSsn2vU&eftEFZhdV$44vHaoxtp4YRPI7lgO>V3OMS?I zFE-uSieQj8LB%h~XVA6{XoncOLqT-}c>N+ML7>haLHi1z>7i8cST9Jwf`1xhvmVIt z>8a)5Q_>Xj;5z`Jnm{?vIX@3PLJI2I!-5b#>aNHT9|}1mAu}B`=>eKt%}fU^n*|N3 zgN6@5{Wb7_JEAGZ5bq8?$EFyvlor&|P0eKpE=kQTsVqpMZ$_Glmnfh=V9oA3UkPY zacH@zke&)^s-);~1%tN9DS$&2qzZHpO(}S;12UQmQxDpqUjV*_Dipf56f{Sf3Ozp) zR0V?Cg`k6hpzBINi3~LC4Qj&cDLCd7E0l6o1XzD@f zoeR3K4%vyIHY(Uk@UmgB#r6!if&pqbcsc@n+!bWt7qns)d`=vw`=y&-0NPdvI^6=) zeJ+9Y9zl)ZveZ1#_!x4sRX|a!kdg^LP76H22@Myx`#^QIo+~jR|T9fe(QJty~426@$Es5InvF8Y9ZHXNY%91F0)2 zNmVGy&&f*!9qtnk+1m@+9vBbuZ81YU^kf6jirgab5()SmX}n`zUTF@fLScwU%6{PU zjI0>q!3h&I!K&PAn@W=pY zoB~t>GK3^1#^+cu#QP)`fR3Dw_W>Q3h2kzympL^jGo1l6unAq+#}MzI%@7}uT2!2$ zp9gX?C=|*POF%=n;06+?$Sr`J*#+tI!OmiUXE<>31@H6#oyY~U72Mh?VTdXR9WIgr zZsmbfBluX2c<`t+Lp*d&3e*w<*_)S|11cy%)5r19wfCUmVep(HEIc5d2X`Q>7~=gB z6EO~MKpHE9L?3({DHJlV4QiJc$3t4i4Dryi6Ix%w=7GSgkip9m7~(;_&0<&!#)=^x zwP6P>TR^+$A;q;7Lp#X1Tp3RVg!nMK(;3aJWK3aKfjU^Qt9RtjmU;8F6t6di?h1uKR0 z)FQA{hJuwsMrvM4QD(M|LZ*V1LS|KBVz!P#mV%W+R(=MkRb8y3kgZ^)keyhRnxmtT zqhO_wlb@1Wo|%=cqmZj$rH~6cH(W;{Pr*t7)DY8A$XBpZ0NwAPqfnq=rBINWT9R6% zqfn?|rBGO!Sp>SqSVy5q!Aha1G$lVLO-G?v!AhYxGZ*Bw5(O)T5{QaY1uKQp5^%3e zN1;r?N}&w2>7+OB8Ke5JOu<7x~vd7yUTzq0n%LzIj<-l zw62x`dLVgX4(P(=)YO8kREF%l0tV1gGN1|H{M_8kymZK73Wj8bW09pyb03P{c09^|Jxiv2ZbX*WaHs~f5h;gY5=*Nwz7UMgN z3_})FE1^tof(*nI1SKGbvdp~ftW*YYl?`H-Fn|>z@j*kfsW~O!DFRR@H664>JG+FT zI5md>=62A@Mu|lXpem#w6Ew!g06TIEx(<*bIW>nNJEthSs)!*uuZ$r(C%2>|hXK@T zfDE57q?9Is&SwQr$uT76WG1I3!Gr!ZtErlgiY zEJ-iQPt9XU&d5*B2Q?-bvh#~TXCP;T8VX4{`Kh@OWuTI&I5Q_3luB|lbF#piDnZ+B zQu0A#VGvaib~2K9dMW4_&!YU)lvD&d<+;ITIR+DVeDSMfp{!3?PO=Mrv+qPBGMw%v_lEl=Rdhh+tW1X;E1s zXv1PsVm4^hK9372we(0bP#1{fnLr?fbOA-yOO>agU@5>VPm&d5wl%g0Oa^N<`_ zkXVpdnW#{nky*e{kXlp)TBKQ;mIh*%g6@I^U7TK;nafZB%I?ry00}Cv3yShVTkjyD zo()Q~*`NcjLA6zBIYU)qN@@;74xAdQ67y1^Tv(C-&7R~GFcfE|=H(?aRAuIXF6l-| zBCt#iPbS5Asi~#q3`h}ylx85tgFOz3?37GUCxHQUVs2sy*vasqfP?}=Nn%lXDg!8Q zmS>iLdkp#6p!}KxCcs89fLDMh;J97@CY!>Lou8YV$N*h!!~mLGNdfg)Agf5hO-00V z8_+5|@EjPb5JVN|8WiyUM9?LwMJ1qS9Av*D14JIY^e!D?1cDEdM@;S|=ND8$ZX8Mi zjX^S`fR=%S2JlLX%R!gS=79PF3}uNqr6q~bQw16FlRynt@RgI0HbY8c38)ZB0Ts2W zpskDyknwBCswU9bUP)1EZXyGyvMNed09_@>kegV*0I6(Kz=LQEDLLs3ux2w#eGYO# zVwyrS$~lJrx}C>8ZJiiPJx$oS5gsYCn;p+F{GzvfX4Z;Mhb=`xXFdm)$;pj4C#IvqMW5u818 zQZm!w3{a0AG_Zyw06H%iO*v>>6*4FRX?ub)0pzeHhSZV_hSbuce1=kRH3vHOB{dJk z0rihTvsw(GNy!}0-mfH3(+yH!GL+>MG31m$b5>GOYAGn?CxT|J!ECSy?BWE_g;uEr zI-qf;q7sI*qFjcu{L~Uqe*m_2I=vu|0i~k?DZIhkzls!667v``R8trryIo+pC^HX~ zhmumu5=%gb80D7cq(W7I?&SbYSAgoSg%jfX&YVufkwJ70oEkOhXldU0{?^lA8m%brf6>6z3Nd zqx2avQF?B09#Z0ki$M}^rULZVrGm_4hD=cSWrC`3-Q2_i@X#bfVp5yy&9$bbO;0QCplaQeJLpsfn zp(-GxC7_ZWJT9k) zC@(>~G{L+6LA%w!mmwgjg3M=t#>_w~=JXgK$2TA;0I$J9=4Tcl@j!c$ia{+S(CAuX zP6?cu4DASjJM5_n8K9F4L1V0`pe7)wsSjEoTmtd}$cWS;1z35NQk0pRk)N6kI_n0c z3uYoj9@KxzNCX|@1?@sYb?2s*B*IjJbb&g!klA(c_3AJw@EUnsWNl&cu6v-rb)@qFJ=HSk~51y$IOA4DVd4s`Jn4cz)CX`LB}@~rKT2u#|B{s zs)02jmtdgTUxZq)G-#<8C~<*ien4wiia^sF7&71)46HJsu!M}yU}%D5BP0VsQ{M{U zdIC~EfOUYzhaj%b1FdAt&j;O+0hUQiEY2^|1?4L+7t#&`GeNW3puw3`knbU310BN2 z0SgtOc``A%q%^Sz6d{m>a1cXa_eZ29CYR=vq-K`D&Wi?169{3@R5oaQ3>-2Hpw1=Y z@-Y|}e)|{$SQWT(N-II!yo`JkF#|a8VMAfW=E;EtG8Nn)%1l9q3xn<*Xdw4Gyl(dRL2cyD8ic6D~TUO?(ya6Mg&MI*RMfoRbMxh6doRIjFh ziZw*74P9>pp67v>2NeP3B+wE?NKSwokEs(;(}Fsz1;q+Qpz&7Fye`CL;F^)4Bryra zc!pF+rUzMr%m(`t6vFVFholfJNiY|qYk>FwDKDcdfP_)10-jupt_8_Vi2u+PK;sWr zDFHe38IOfIpuJ0=)B$dEgF;CGl9(BwMO$i~0_gmcoE*^3??g~B02+D#WeNq*5#%Yb z`!`_fLG5!;8VB9=0O?;q4T4I5Yf(_A2w_$}WT9$e8YF9hiV;*jpd6J7TI35F1cO@- z4Ng!bLM;b1O)}F#Zi5PdS0q72Ks$s%H^7&HW&}W48GH>PH0v{frVl|ECW8(OhBhIQ zs_^vG{M^(MaMKXH)B|*`1!$-QNgO#>V+tcX1a$Tbc<2H#ilLATZxtbY&VWZA**qj= z2+g1Z3MHuF@d1)Ss6(~{6m8&!9}d&=(;#giXzaoKf#P$7HJ~~S954;}Rv7a0K&d=4odHpdf>=e#iJ*Z622kMzDN5mk9-wnjp(i&4GaxnM zApIEyj2=Cr*aE32Mk?;We2{aI3OkS(=+=$YOmOoRnxMh!u_1*RNCA8d0(^u(5xBo! ztN^az5_1&N5|c~vixfbY(5GY;r6z;d41w!;G^c=uT_6P|mNFJ>50VN9AB&+N3DAX` ziAfB(pyRS3IUFgWVNc2U6d)%yWOax%3W`=lB4wBrZ@X1m}R#6qa-i>M?;jF_394knJE0@+i3K&&|x! zh1>_9o1c;jx-GS+gdsOSFTWVH1_D&Gf=V&aao8o$%n0TqIhP@~G^ZpJG;IK8fJ%56 z12o2!3%a+otQ0h23@XQ9QlNvMQW^3RlX4Ov4HwWH1-Kmn(o~X}47$A)UMGP<1d?V! z9qgj?RESIo_J#wbSpv!d3VHd-8OXs5YocJ4glA~5F7!?#B3)pZid_mhIiRaR4nHI| zhRHbOkd4Mvf=Fv1k1&8UFsRv8ngs4_fc%bC5R@noc>$?JK^_Q!L<3|i2c+mgmPHf= zV9|2WshxRPiUDL<(0UY5PpCK*JmCYHzROcUjwnb1K^ZxK)ZC!ujYy3ya8nvrHykX9 z{F|0INVMlEBW#8pb$f&;lB4B3jc2v@HqzzC>j{x_JcZV1)v)w4zC6cUS+1G zf!0%&WP-ZPxv9k^W%)(fkgf};X#?%GfX-6}udhu^gOtm#j!$Y~X=Yg>Xwnz#5Qr8? z>kHM1;LZ?48WcS6sVC&ffk;DigBy9EYd;l=AQy--z`C6UMfspJQZiFPB4AcNI9Na) zOHT#QEr8BZg|+S&iV{mQ^BIsTVn}(2E`VH&fU7r9^Ex$~0m3fAtf3(i3ZOz7+{{nP z&re6nRA6c3dK)4D%AH6RH&_sF%?(yj40i^!?uLjGQF%iZVyS__GSDg*!iM`1?2VEv z=+O{hNr+EC%`ix*02Ks{uAqb*s2c^oO9&DEAR+iDO>tsgv2Jl{QDz#b@T97Z zAkZ%Y#V5Xg7{oZF&KA^FNFw0WgTo!@$_Tgy(o2IX0%h;~eB`ldMDbl!nh6@_2kmIZ zEb$3SLd*T)v{YzM29ycFJs(g}m8y`OSb)qcMeq=X9b5rI2vjg2m4EP}52b(v7jRfq zK?dR>t!}tZ)G`peFfLnB^g>EKTy{g(Y{0z)?%IJGMxZ7U%vQ*7C}Q{%Ar4Bl2p+iI zhTww7GK)d2GbB%g`G`DKQk0nu+I|embI1iMqNN0$1b|e)X#Pd00jEO@FXrc@mw<+! zKwW1L0}>KA%YPihQy|@tjyJ-3WS1h#qm=rfiEYquEp+Yz;sq2A!a#5pgxs>g>Lbvd zTt#I$iPbI5Umx9mm zK$wOs3eg4Dvivbim4B!#AQm{8bMK1%CnNtcWjv+-c zWV{!Vx50c+xr9{DU}kc#DsVxMWD2O~1|3er(y9Y%K~Vyq6@+xM(MQt28jwcPz(Iy6 zogkVRQj5|Rz`YJcD;gmNE(>=Rwj6|6&jnM`vc0r+XF%Eqx>T1L@HKwpj8T>CN?&e5aWnl zuLs$ygj)}|Ohd5-wDl9@s8og00?;D-ywpS}g;-w+TE3DBnh$~)49Wta5-kzDxgEtc zs8;Bq^PuhJ$O{%xR--_bLX5=iKXfw)Y6BN@pal)64l5|i&&|xq0ryit8JVFh9h5^0 z(n}b?bv%g31vOR~KoJkxmynv40@{-WJwOxGKrYBH0A=n1&`cO)l_F#ZNkMrE1GuXL z+EjtE*eAQHC@%$+6G1f@#H*mtV?bH?mt6%dC(=`kQqwcRjn5+RTw6g7XflMMD7B=t zC=b%>Ky*Gpi_ z3r8d&NQfc}AcZZGFg#3=#Gs*zB!U^vNRrSHM-qVrJAR>(e9#mv_zEn7X<05q`$zKhPGCOz>h6P<54= zm#7Ph=Ts;M>@fzAcfi>U9N?fKDUj0{5Do?{6wJ(LfH)4a>Z$~E=o$mub)W`eaVqGN zRt6N;A+;!>6NwNCR1q>j)=GjJq7Xp_&~*Ks^%$$R3O0YNpa5uNN(m^^Ku2kUZchMB_UA$NG=NSEh3-;?uO9`?DnY`f1hje@ zrP6gw%tPiEGkE9a7l4TZ(BAyaEZFKn*!i^JJ7E}5c*P8$dlkS-V;~IV`(YToVVA-n zSn9=~RjJ7tMbKsSu6ZRznW@DLZuv#I;C0!lc?{n9pgjb|C72A*K_mr;OJNus)4*jZ zsMbU$+C!V^K=F9xU7s(jG-Xy8@+ z#o$pO$bhK<659}oZG^-&Mq-;Fu}zWKW=L#vB(?<-+Y*VLS*#1mN}zEkh*Kc#IMBct zXzL(C95gJ3;DK7pNajE_fm=~fjo=gC8D?t$@2&$P@jN$jA$N#1OP%MsyCqlf{=z91Pc;aFBY^) zA3P!fE_E=k6@9;STiuI58^b_FdJ#iXiEa*FEo4N#vtGc^sgUknr+prRbSe+p8}fymS%1<PXk$n z10HBCVE`>=X8>&|E7C1VV#p~ef`u9Q_*L*sZYlg6TJUHUWC}eohXK-j0PPM0pLY#i zTMsrD(Fg(`LBmjxS&^Dkj2Mal4}^h+YQe&wcqsx66F`N*RTHT3l$r-!+^PVo*`eoA zL;BT-zBk;9WvN9V4>Aw^!Z zfUpwNilGBBB?`F=;Bi3E@OUCP*g?n9f-Hdylwb^UgQP%qDuDL7f)?I`1YmO!5GN(& zf{VQD;u3~ZlyOry4{6*KE(RGlErkt|g0c>LAr3=+UJ?W3q&P&d!dN+}3ZP^4khqXu z1BM`YUn9t)naPQu*$~*SM(DOE(5(-k!}vkxtbp=6To`hsE$FmzhNPU#?6RB`(C9wo gP4ykdq5-Lm|m+{|>0z^X*?ekIIrm8p3Q0Fu1T2mk;8 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nn/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/nn/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..ee3e57f2903708f14b56aae01fc2152f4f33e66f GIT binary patch literal 53117 zcmca7#4?qEfq`KqGXsMR0|P^fECa(s76yhjRv=LZ1_M6^1|9|m217pv21W)320K3n z20jJ`1_vnZ@5jKPz`(!|=f}Vxz`(#z@5jI(!oa{V!4G2IQmFVLKL!Rd1_p-9Q2r}F z1_nI_28Q2$3=Gl?3=CTS3=G^13=D4m3=BdH3=Bd35PMRg{1Sf#1{DSdhIW65eQW#~ z7$g`N7|!}b?0x3Xz`)MH!0_Flfq|ESf#E-t&l|wNz`?-4AR55Hz{SA8AQ!;Ez{$YC zpcw!$-xx|e1wix%Le)h=)ujY5FvK!2FysX=FeoxGFq{d1_~Tsw#D3O51_nWpxq%D} zq6`cS27wF=k|2KsGBEHnFfb$pGB8LnFfbGZLiBY*=|zDI46+Oi3_AlE7~~lk7_J9G z%=->iFAxL?2kjsR260fh2SN0Q1u-zFF)%RX20{Ei1uDKYh=GBbfq`L95X2t`f*|pB z0xEtLDtwhSC#*A>lh6N-qqCn7U$5h=OlAx;j#d#Zha`keLF%S;eRL;;_nks`YKfXQ79xGy$FS*KgKXf zI0=S9^vj1q!bKBGTZcj1=^MttAk4tP5E=$?Zzhyq9|lRklfxkHUKhr|pv=I)a3Ktm z&c8s#`NARoFbIc)TR=F({?KrU{i)#)_ZEjk!oLB^Zx4s0=PBV3fA0=wU{GRUU^o^I zDHmRbL+odbfVf{F0^(k+2#CB<1jOBb5s-2xDFPBcA zVAvfADW`5lLfrQs%9oCUxZ5EL;w}#;KNL#GMnS?eH3||x^-&BA>I@7F6QdyceiR`TgE}mv5SMmn-^3(Fb)!q zVQ~=mB}4UB#6i+gR~#g~r$Y75h3a1k)xRMQl1{cl<#)$1FxW6KFdUDA#4}4gBz_g+ zA>peP4+(dNc!;?P@sRYG5f4e{Me&gGyeS@%PZq>O{B;OQUyFyh^Hn?~p8v-~@~LD3 zB%F;BAbhU`NVq0L=@uxx6iOe1($AqZM2 zL)=xC49O=GlOgWikPI>ZIF$c584`}ak|FMvNP&chK?+1)U3+EXCuX?Y4H z+)t%I!tqTC#Qm(P5Lzh}lD_OyA@LfR3W>+4R7ko?g7Py{A>~0KR9$^4B%V8<@{>{_ z>24O3zdRL^Ue~8W(%qI+NV?je3Q6}zQz7oVk_z$X_f$wY2&X~p(MyB4!zPV^!I*)8 z!6gln-Ye1|`MD(xV&Bv>h`Sf1LGt}-DF132#J+n_eNWOL_I*f$xLY_KQhv#%L)__; z4zV{d9U>nOr8CnZ?k`Spj!3|?6b4B89~48>Ut3_1)94D+)X81zBy!z=~{Q&2k!N*iTE z+?kOLvA;4K;;&99e=(HaoDK2!;cQ5Foymrj7x$s`muyJB;LL%fWAz+JxLf8x{2!15 z@o!2Fq&z6jf!NoX1IZ6Fq3Sn5>61`(4{{*s?OP5c9++|=>4QBNqF*$Zfx(G^fk8DF z5hGOJO%~>1_lP}JO&0s1_p+lJV?0D%Y%gbaj5v`JcxT$^C97EoDXrQOFkrD`{YBy zBRC%tUYYq2dm8c~;nkJTz~ITiz%Vl(5{{4aA^GQfKExeT1rT$U3n2EG6hQp%Q~>dp ze*r{&2vokj0FqBy3n2bnRR9U!4FwQ;_dxX>D_~%7U|?W4T>y!1oP`afAQf_pW zK*D)Z3B*6gOCbKZ3^j+j6yhJzQb@ciltRMK1j=_Wg_Ot9r4aX*mqN^KEQPpxW+^29 zA1H;`^9m}?Uj}inSs5f8e9Iv2OfG}OLsl6iUaFw{Zm9a%Wsv;5sSM)p<7E*0AC^Jf z|F;a{Ue0oedqm11;&SB>^R=MjhUJiSXI%~nCx>!KeoH8agi}3~ZY_tT*Y0vie9nZ5 zFD!?+Z+SVyUpt`uyHNG-$|3&vQx1t=o(hP4q7@KvsS1d>S{0D^w5WiDYh(ojgEuIj zRxmI)GcYjhsDR{?KNS#va#liU)k;YCIaWgSM^rK}xH2#>R8~UVxgSa&uY}lt9!lS+ zgrx6>l@R+sR6^YKuM!eo%vBKmyj2i;MWK8pD6Lfm@wZVGM7?trr2g`)g4mM*r3;~S z6;xj{lXKX4MdV z?$r=?`&BbA*1M$cC8c4dj1=armD*h5`&ljjZwpxff z-dcz|g=-=9O4UOAp;QYoSHBiwzcp07S1lww0-)*=q5ATm{IXiexJENnyd7$OKa@WW zDnAcu{vxQk>uMq4vjr-@6UyIP3yJ?jwGjWEfy!Tp>c0)u{~Rj*ww8f`iGhLPBUJwv zsJnhb&0(v9_)nk?k}hTIAmN~02eIF<4&pzvI!JnRuYLK=W)I-F1 z>LKnGsfV~-yx{}Q}vK|xB*rF6l(vgdPw+ugz9H#fbdxw zApR0=fP{lw1Ek%i1m#CGK*Bes0a72NHbBbDo(71&HbT|yXn=&$T=LhSW#gt#}X5n^vtBgDS= zMu>aUq5OhIh&>gJ5O>u<^>;({PlD3Zpz^bz^2?#-u7m2|3{|%iO7Crigxf(V{|r>! z1*raOQ2Xyf-Tkx?QXc(-suyU2#GgnL#Qh3Q5dWw)LHwuL1o4jnl(uMs*yjLM@7)CP zPXJUt7RpbB@{6G6RYBF)LFwiuNO*KW<@=!eCN)9AZGICZU95nbv%Lut5Bs6|&O+5+ zhU$L+RsRI4|1;E`f1v8vn<4HLX@=w@#b$^VVPlKx41Emi_%{|r(3EvCNkox6OGbB8}HABMrS2HAB*;*jtye$yEAe5GX(()}3 zcc`^M+@;+DakoheB;4$v`dy%W52!xB7D)LR+5+)!L<=PTQlWHi3&b6zQ29nEzYofv z1+{NE)VvK)ecPe(`=R_ZP<2Qr}gJUbi-yW?H|N6E<+VkP9koHMcE5tvuTOr}F7^;3HRQ)=r`8!%6@o=&g5`MR# z@=u`p-$C_%YlXzaAE^BdZ4h^`w?W*&*9J*wL#qvrB_1Lt#5R^K?MML!<-ZA6Y1^-T`r!VF$!L7Es!& z1LBUD4v4#wpz6}0=H)@@vJObN)IrsEbwKj-1gO4cQ2EszkZ{@#HRlji{3KM}RjBwa zsJe$8ko5be0}|eUp)_|VBz;JBLi{7!32~=dCnWvqbVAyR{+$qar$g1}K-CpM^_6u( z@Rose|0xf2pjhoR=2g34cj^6x?ECs6xdLFL~;&HV$VS-T+a z=Ies^L%a*(PU$X)eF|NWaMJ67_{$Qi&b|v0kIr3?^y3ZXM|45lmCyx=*L0}*La2Nx zRK6B!Zwpj^FO)wEs(vxlzU5H)wNQFj7bJd5 z85sU_LBct<2QrUZ&;zM&ilB6352SxFp$8Jqt9l^)q+LCbe$&MsNICGf2htyB?1j+s zy^wK3+g?a{RoDx0=cHbUdGmT9`gim~(&Lq01_nC@28LI?ka|V457I96?}McKtUgG* z)Ij;IeUR{;4i%r@2Z@&zeUNb8+z0W;UMPJAO5g5-#N#Wd`X7A^3=s?r49xwIerrrW z#Qin>ka62t{g8CNryt_(v;7eNJnx5u2gd|RKUZP`#6RW}Amvr?1jx8h4wOH20!071 z2@rpsm;ed)$58&a36OjtIFW%t7c>t%5#sOgi4gZ>PK2b#_K6UGcTa@)WAa2uJ-2Wo zBz%@Y`D>x-HcW(s`;LhW4E78R3`ZtH!i8lL#D3vP5PQ`oLELXQ36id(CPBMbTi%5Trf5c}gML&7U{|yF-ww6sI8@&?sJ=T;d!9kX-$C_#nG6ZHzmp;HE;$9#J~EmDF*j-oBwZy> zfrNMS6o|j3O@V~(!YL5{t)BwP2m7Z$+;w#dB;Ia8^*x&c@%PUukoe-73Nc4%D#Tpf zsSy7;OogcPnhFV@=&6wKDVPdzU&T~N`kOcvk{;Jgg{0?WQz7Z~`Bca}oWL}QI+JM- zb^g;Jv6 zt7k&OdD%>e`gJoQ`uEI)q|2jF_19-Y{PT4tqy&#Gf5=AmO!n4rD&zZMU#W&4|xNG-( zNVpxH56Q>Z=R?x%_xTX_NGyPaqxJ%bIc^Ie^+5tuynX@1{j(N8;%oB)NcdcY(m$ZI z{6dJh8AuPub6*N+P!=JG9qxJP{vBwctcg4iDq<<~*wr!IoHe;ZW% z+9F80dAkVWZqCIJeaed=<(Ctb&VtgDp!6;%{Rm2PErFP01f~6!K>V4t1Y&N-5{Ua2 zErGc2@DhkSZY_a?_pc?8_z+qOQD?FgA|ARFqCa;jBtNt-g@n(Br4VzjL)E>5s$*LQ zi4TQkkoY!U28mz$WsrFEfYL!wItD7A234QG43e&@mqGGxGgN-!GDv!z1=Tly8Kit! zxeQYNY*+^I|G{ODc)7a_;=W(YAn8(YImBGK<&gG}+Hy#~iCPX(pS2v4zS@^V+&ObO zBp)tb4sriQsQz0}`q6R*1|v{A32Kh)3P?WHT>(k&5i20>k6QsTF9*smTLE!T3sijK z3Wz^uL-j3M0V&^Ctbn-h)(Xfx!z-wMk(Chhl~zLXrN&A~Jld>;_#ukR69J{uq3X+4LBg{Q%Ac_cQl70?1@Yg_RgiSVy&96vjaEbWQBZ#4YRGun%GC@E zE({C|=T<}N1K~B0a?f%N#GJe}ka^h!Yas5pxd!6i7i%Et_s1GYcnhqBxJPy^#NGO9 zA@WvhA@&5Vg_vKy7UGV%Ya#ji$XZDF-CYYQcfYTNCh=0yP&AkCN_wIT~JiS>D@z6f(mYX5wxNL^#i`WcVw-dV=qHoq_NIqQyrLS*>!~@e7h(83kK+?JN7Ks1!wm{@< zwm{tJ4V91H0XB9qe&UU4|YPupF`=lQ1zd8LBi)h)Eu7Oknj=S4at8hyCL#k zyCLof-wg?ewB3;O(6k$3UpG|W#NCkew`eyceQekb@$b3ako5>pb~7+|F)%Rb?SZ(v zat|b&8umc^y2W>Oob7ud?mxO0;*N8BA@Ol_FC@Rb*$at}KTz{T_d)!xxesEF#Xg9B z2Po~i50ZX^_CfqxybqFYJE8Im_d()w)jmi(9)+sA2&JFzgV_HUN{j4=*rN@ljrT*= zYg_MUVDJIuqy3O@c(xzn&d>WH{@^(PF-Q0SBwn-*K*SB8wD|!@d17|}lI{Ya;<*PP z?kYI|3CD&55c{VdfcSIn0Z2G5I{=BV4F@3MaRI9TK2+Va1Ca9NJ=C6GP$}jFH@oB&4BV3 zLe(uf2uTNPpyqFYnzQF1Bwrqasy`0ppE?Nf=Xt1kH=+6;LCt#x<-dc{pP>Hv2G!4a z2$Fu-4nfKhu|p95X&!>O*X$6)A1;R={_r{k@o&%}NPMIpg47o+halm*>=4BLTMt3p zwG&DohMIF0%D)U%clQv)Uk?vK!uJ`}J@29B{fEl)9fr6=_%Os=$-@x$C?AHzgZ5#F zz2;DHYp8nX!w~a54@3OvcNh{safc!Ku>@*fD^!0!l%9MT693bo{CQCG7D4S>0p)Lj z@^>AEq?2QZA?fuZ)cnU#bzh+F_ytw>A8Ibw5lA@m9f8;A?f!AR2}Ovi2L}DLH%_M z;!Y_jEq4rJo)VO=165}L6*oHu2^WWB5O;eVgP0!&RiAwf67TuPApWU>iZ?>_w?gUu zV~}v0301!c>aMj=^EN^4*?$ZY?#H3(uR_hc2UY(FNOT!tcOFV#IRPo3Z$j<4a{>~6 zPoey`PA1lMw$IorLJOgsO9d%KM*$*b@PjkB0J-PeS~a zb`nw_XF>HfLG?{I2`OJ@Ld91@?cI425{^esLc;IVNl5seKM85y-8>0tr~H80Cw2;= zUhWh`y~-(wJ2g*1;=%9~Bt1An#e+^k{1pY|CqwmTpMtoz@D#+qrBL}AsC>&QhgJq+q{9VJ^;=Fs!f!X!9Vbsg+E3@8<}jXyxQFvJ#2(4hkaQq>8WP@Gry>3@h4QUW zL(F$O4e@`}X^8()PD9+E2~}4FrE5<^@^uGP-#n;&n@&UW!67LB9Ms->ry>2+*HH6W z&p`ame+J?%u``fzPWcSPUuI_@_Pd;cxYP3t#9jVS`ADdII+V^i1Myek8HoKgQ1u;W zApV~OwQm}fKNqTRAynNmD7^tHzYA*bKB&GUQ1eei^<9J7bNdV=e4d|yq=OGo@gGq0 zSk6MyBi~twf7H%G+@}qt&Cf#o=M3e0o`skb3KfrqiYK3igiroiNcc2C=?P~c{+o9e z5{`?`Lc(?ZSx9-Y?JOi*Zb9vT3RV9KYW_PY{pBpAz5ffUPV5}SU()9w?o&Ajalh6% zNIdADgVM!_c#x6chGrAIK@NtWt@k&D+j8-1S(#69x`tV*_8?*r-2sc zf%cj*FfbfqU|`t9$iPs<#K16*fq`KfXbz5%fkB&zfng~V1H(?x=2Zp;h7x85hDazI zw60v8nSmjck%1wFk%3_s0|SFS)J%{KQ=sbXnHd;LKmrVqHjFVd1H*A91_pU%h+o4% z8!w^qps}o@Aa#rk3`-ap80r}r7$z|=Fx+8cV3^Lxz;KC?f#EzO1A_=71H*r)o=_$R zh7KqjMC}9-3=9lhQ2XnkG*lQ&1u;X$bIy41vrH49gfG;|gg^3=9^`3=At77#N(G85kIu7#Nlz`Q3$?fq|Wgfgzij zf#D|;WNo)BBLl-vkXxYYK>Jrgj=2Gv*JWg2uwi6iV1mkl#6h@*k%2)Eq=$ilp@kVT zHoF|ECIm`XGBYsDgsLfJW?+bbii7mSuqo6(yO|gm5}6qoni&`vG#D8ewlhJ>hwqFG z44;@77<3pR{jLj43=Hm!3=H3)X6*;<)nH~|IKjlg@Q;y!VKoy2!+EIT983%hQ49f zXlG<#Xk=nw_`txxa1Er1fq}u85i(X12lZ<@)K9g{3=A2J3=GE^A!9#(pyruD>3-0B z4>JQpKQjZv76t}}XhsHxZbk-%9%crHql^p;u~2n$p)@Zjj2IahEEpLW;u#qjCNeUB z=iaw5GBDg_U|>jPW?+zJW?(31Vqmz<#K5o+WERwoAZjZk1H(2328Ojv3=Bfd3=Dx# z_k!d=d!a$}0R{#JStbUC5U3y685tP%GBGe5fx5wv5i*_vQVYV%85tPr7#J9yF)}cG zhN>xJWMC)&xs92DfsK)Y!JmPFL5-1t;Wr}#!+ItLh8YYD3{4=-Q2d;Mfnhn+zUNE~ z48Ne}++}27V1>F-l!<|1F;smh0|SF8BLhPwBLjmYGXuju1_lNNsD6+VW+ny(111Ir z0Y(OfJVpkF%S;Rm^-wcCnHd;tm>C$-7#SGUp=O&fGcYV?U|@IvW(rd28M2C z28K9L`2sQkiVK(-7~V57F!VyzaWgV7ykulxC}d<{n8U=taFCIKfrpWS;Q}cCg4V`B z_3Z)e?}xHM)KMk|hI|GFhFT^DhWVhfikX2ymYIQpi;00jhM9rkEi{}LFf%ZeLhbs& zz`)SV%)l_0k%7U7nSo&)BLl+;P~HZW!%Pee`pgUr=?n}EQyCc;oIrkLVqkEF`Y|19 z9?0%npmYe@_Yal($jHF(5lKFYiGjhKnStRM17zQWI4FNIGB9vK)q~6c;aN-!4AIOC z3^y1V7@mUiBNGEdHPoD7CI$vGMh1pwpmG9KU!dvDgQ}YdD%Tkq7;G6C7#1=xF!&>> z3uItm@L*zKXkcbwkYHwDSOk@e0hNVNHfUdR6etWq;SS1EP;rp^>OkcoXdf^WWIiC0 zfq_Ask%8ekD6T*Xpg0>Ez79+b3@uPLNNPI+14A$~1A{jcq&<5DDmRsxf#DGY1A{XY zWE{VUk%3`9BLl+%kS5SM5TN`9WrL^$s9)Wf7#R2%85n#S85o+F7#M7s7#NJ8av*hw zL3{K-=TR^*F#Lep^$1Bm3RH$NGB6xsWMJ@PW?<-qsyPKp*NhAd4;dL4Rxv^5LO|zK zWP;{KK;;;y?ZC{y5CaNB1_p+gObiUU%nS?y%nS^NKyd~QGa*I>hFnm(U|?X#WM*J+ zWny6HXJTM@&BVYk73z)?j0_C#Ky?N)1H(zEST*QO2&fr;3=9l2m>C$lm>3vlGczz` zF)}c8FflNkV_;x71@bqj9tEXiMh1oqW(I~fkeeA881zB;4Yc>1k%6Ix3DQsg3o0|2 z85s63F)&m??V7~Mz~IHiz`zYEznK^q-ZC&S%z@g?2C8eJ>@ZN9fr){EjfsKb3pAXr zFflL`FhIs|RG?y@aOZ&P0kL6NmkH7*>1JX8@9n+=RWHxTz#s`K&p~O5iGg7OBLjmX zGXukQCI*JJFwG!$GchpuGcqtdVq{=YhPr(l69dBc86GBGezGBPko zLG60M#K6GF%)qdN2{LbShKYee0xH+a$iQ$IYA#6cdIkoDMrHWd`t`sOi*<} zQ2GH#5d#Cm3MK{yevmz&b55Xg^B5Tz`jEn4DKi6u1rq~9IwJ#v1``9rZUzR1D^UGY zKy5Qn{lUb*Fo~Ig;V}~f!*xc;xMevr1H*J?28PW{3=H>~7#OsW+;@wKfnhZRq`v?% z%95FZVKpNIgA1tr%EZ9H!^FTanTdg68q`f7H6XkRYQ{kZ28NBG@_>B$1_p-rAPt~1MnLUXX2^WuJgB@CGvu5Qs1h)> z4%DUqm9fkW3^$n=7;Z8!Fl=CCU=Rk?XGrdl29;l+Z~^Or5U&^+7~U{3FxW9OFkEF~ zV0h2Ozz_zJ0+SO!>4AxX!HbcBVLk%`!zWO=4yrR485nMW>OWB34r<#mF);jPWMKFP z*2Tae2nuf`yFq8eK&8OcS5Wx@m9J!CU{GdcU`U0AOBa+*0o8+0e=lKRVEDkqz_5au zfgu^x4r63sSj@!0AO)(67#SGM85tO)nILnpU<()+7)+q%Y-M0z_{<2IcUFLkfz&86 zF)(C-+SpKc6f-g~%m(!fm>3vXp<>{}c^DWN+@btcpz?=_fq@gsHv*Mu43M#h=}@uV zpgsX8t{E5@I+z(44lpq=oCURGnHdC$1Ky4vL28M%B^}$d#ZDeF%$N@PFbRG{g z1H(C}dTw1JhAdFqmw|zy1{yx@%nS?@LG35dno6j7R-if*)W(FG*~h@Z zpu@z#U4h6&U-hHFrH5dSM90|Ot_pV15q4CbJDK~Nh9 zBnib83=9mXLGcUZ7*auH4Jbb{GcdenWMBw@nk~i5z;JY*618)TajR0R)}r!~hw00V%l$ zD(9eno(&p10F|wv@MmIR@B{Vt85kHEpy4wUGzI{w_d)F^CI*J@3=9mhP&trUpfj1u zm>C%QKxq=xCkOQv7#JAjKxv$bfng>S14A;@F3|d76)4*b>Q|5%pmVd+e46V!z460D`#GraTm>C%2L2U;{1_o|s28Mf3cU)y; zV7LwHM?=+t%u$ERf!HTO=Y26TFnELNE|37I+=kMnpgIk7ju7a~H6{jzH;fDn*Fbui z85o{0GBE4`wb?=adIrdND1$;uehCaSs4}SP8Ko&?XXfN5RhFa{L%6xA>4{Koih^pf zLUKl8QDSmQY7v7fD!&*c08$B~!2-$oIiL00xEMve zAhjqtHLpY=KTRPeKe;p)#4bur1nYsy>4EGlE=WvHg)_i5l_VyC1WFQRTMYB9)skP4^#qLkDkh2YeZ zlFYnxgm6(}W=>A3f@fX|$i)02xcZ{Z^o)|c)MB_&=lq;}Oaq+r^Gd*}JVn6?ViwE< zh)i(_oL`h*T&$asn2E)Z(xPH4W_zbrCgmpFF6w&JPIzE$)I3LEUJV#BcL=dxug^#>yuiRngf#v2Iqv#{5;IS2rfx1Dp5!) z%FnfesSW`pV1=Oka)n@UM8U;VD@qhFgFmDwF*!RkFC83_jyaj>dEi`x9vxw+MM?R^ znI&-7M&;+{qDPy(y*-1Yf}?Y2h%1Amg0p9kbEvPIk81>jqXJ04J;*T(LtPECQQFN8=u z%#V6{dJK*^sYN9WjyXA?!ZAKCFEyu_!7-;K-UmzufymUNyu^}J2FJY2TyP{YI2IJ- zfYN4WejbBkQBi(5gJW@VW^qYkUI~L^Nl9XI1}G>&Oh}Sf@Jq~1WpFGl$#>4rEyzg) z8CI5zXGIKKXQWJ|9obvM& zT$3~M8K4;_8I=01V7%hYDvGzKRKI|!6(V4VCk1xQh@#{kV6Fj~PW zGY?c!7c)2&Wv0fbfhcHpvtn>6Eh)**V{le*c6IUe@o{8ujxQ}L0u{PB`H)=C;GCF~ z3?fqVQWA^c4A-*Myb?GsEHky7!8tLnEU}ouIkBKP-X}jf8^i)-2nOfWoE$I#DgZ$o zh2nz5ykbzj0C96ML>4YulwXcb2%Ml*Q=lFNsmLoyElN#ca889VxB`muK?y7~KQA$d zE1iMEdp^$bMrh>6H~yP+@yR4SQ1E4C@x3^C%aT|K4fst&r2^#EGf+aC$eG? zzXX(ZGeLC;m{*ioTw=xGj3~9BNdQTtI5QrU4xlAE1C&;9%gjqraLG)}$xnxi`R1o& zre&rUDR`$=7Q;mYic-^3i&FEFQ?ZIEq~#ZZ;|Ee@CkS}`i*fXa3~G$qC0vRa`a zvm`kKhg?x&Nh(MxwMZc#u_&9t1=4_k(OjVgpr%1$aVnQbWkG5YxX}VtqYzw~SCWwm z@?jB7y+RT=H!DEW6{u;TzyKmk@(bLGKm`?)KXBU?$#An0m%JibdB#>M|PGY4(Zhld!LVf`##}~r{i^1`l zh$vMR3J|Ff6#r?N>7_;BY@v_>PQ-esT8U7euaK8t0?KlU*`SiXM4>1@KUX0yF&7lH z`3jZ!r3&SVc_pB@&dE>DFD+5X%P+TAP;dp6848sO`9%tORtgL*(AFk{OHpEZW?s5u zQEDQCOJ!bSZe}vH#8Ch>bW@8Il5of3-}TyqnXiwjZ{!37zpF&CU#RF(#n&;sVOO` zDWKvhKMz!DyMn7(SQ|>g7t*@H3=%YT@z7=v1G+f0T1OMdXQD!o@ zOfNucCuM`mET|3fX&?zuGYLgBJGD|F6;xlsl)0;(8X2&YE~`U9uVr2L|IP{jfDKyo~|yn?wt8B!0#CuSC*34t24$vN?v1u$_? zFeoHdD#VxP7p0&Jg2Zq-0VQa0s)7YIP6avnpgJx-9VPG}f)FvBI#Hqso2nF0ClK6H zf@Ia?3{bzyN`V2)1+}C=`7lo*H$Np+PeCD|D7Cm)Au+EK+3vqS-*QwLNe6+;TD)Z*mCf>e-xJ%}YB^HRV%iWSmw5=#_{Qp++^%OO_6 zlpxH4y8>!Z35IQY46YTKpk5J@3m{^}C?akOhK3Ao3Wi1uZkai$uttX)sQ*;N0IKuB zgn~b`xOL0S%Ph_S^=tFNy>bQBVm*)w6hV+kQE>^lXk>89NlZ^qO<{1$&ntl&pPvsJ zL2v_g^&u68TWL-Xv?aiR#O4agF90`1xu8u^P_vZFCpE1EA_{JqLYR0_7u-|xQi~FE7~FFbi;Kb4m3uxY{t;aU z2p?R_!vqyz?OQzth-?8UYV%8r;XMr$6{*DvDf#7j3i)}d3dyNCIUrrBpeRc#K^Fse zX3+&p@)dFti%S%8GRsmGic-@--Dw8*d{Ap5UjgDUP^Kv?%?GszP$b|(J5W1Ipc>Nh zi*g}-3^WN)B?HPGiJ)X&mYSnrNJxPZAqB>S6qpcFU`j}V8FmF|qB)6qDUfa;N*LuN z7Nw^uv< z5Yi|~2uTQ57&g2q~PMXk`-J5_M`=uMonIz4o?zf1R*~S+&%{l^&%V# zl26M7RTQ9tP9ZZ-AyEO%WgsQs;ta0}aIuD-CqY`_4#Or18k59yS7`xCiJG61R0+z} zMX9Orc~%V2Za9d_%u8qRD9OzMjR+=Y=A{;adEieS@?ytK@sTs;OK*DzNfQ1`|sF)1~N!6&g2G!g?2 zXP?x>BD7W+YI{hJ0p3(#@X1V0%_~k-a7-^sO$80EDS(C#3re8E^9{rDiVEPVVjvsfWNEsenk(%1sE`f@-+0}ADdnI(D*zVZ3RB@BqM5I9RA zB@^6@PSHciBE~#@6Ek!4{Zh+|8GI9qvO)PS2{Opd;G0;IoS_h(npcupl&S#A%?kN> zIh72)sd=Sf0@MKnalj7tO)V}?Oiu+5AtQB&Rf`#XQ%e$!7<@DHQo%!$AXa8>X|6&} zYF>It2B@{23$iISMFBKCWyRo|SqvV@N=*SkFgqdxn87b!0aPhM=Rftpd{6-dV!+xFkhxK?9C+v}3Eo;OMhGHWVn~9}7Fe+YyoIis zg3tn!MTj6bPmqks$%M8)(8N%<@a8L$D7ZF9;-j`NkR*`X6%gU#)S|M~qGAPj=S`0b z6ei#qPjt~d-O{{FPyjH12jM{k7ktjcFTVs-#KD^ue)%P-3MCndCE$n+PAZhuKeSf&R|pOX^7nRS@Q2P) z`4^<-L3;ftL+P+lNJ!5bT%QGi>VFWS;0GT+VgSkHfJlfL(4rbt!h;7xp@kHrya)hI zc7Rej4prbDqaH&*Vo_pxQDQ*`LqKA2F(|1s1f&*$0ub8K1kVO5 zAvA!^gv=iksRQi5#Ny0kh4PHlqEv;%Tm?^s`~uKK9=Nv(cMC{iN@_`BW)7%gz^*nU zKQFZ;GdVFQrxG+Yo09_xCTtFel#~G(MTy1G)guFFhzK;d6`GfmT3ih0=I7}` z=eslWK*0?eAxta=xg0cMGBz80A*$wBn_X|VgOBRF(A+G zE5w5uGoXQOXzL8@46u@7*a`qto`ObZnnG~~Xp*WpxhS)sM4_}eHARylC_XjCiXkX5 zB{Ls7F$iXZn-!pmAO;WtiAlt?vqEBVaXx4c9F!VBttwFZfJHQ@Apt6b!PE9ddJI9S z1v!bykcJ*~b~h*$##TP<}b6w~$)I5FDRhT9lj$%ehtz z!HH$5@IjzrJ%-@q#GF)x__RdO42cy3q-X-QxF9UB4Z*32MW7~HQetv;d16sYF#}X2 z89FVj2NOukFS3HNL2ZcqB5*Q-RLgmwiRR=~P(v(Hp%^^(4bz9D7E#mUQJxRiz7MG;vg1mwv3$6%2qIo5tnMQ`- z)Ph9FN`T;0NYM_R*C@#cr8$MfVucjw91CI&1RTkr#$|2El_~RC2Xu2 zk*7f;lbLy?si4q8RqB(Uo(>v}17*)V(5!!OMrK+GLvTiZIV^7~#OEev<|&kC=B4D9 zLu5)oYjiSFa|#r4A+33a;Oxu-h4`eL#Jp@s7(hfovqhjbbsB~r7=m*$K~oID`SH1_ z48fqOAqc4u5AL-m=jRutfXks`n0RJhN@`vSxby&*S)hd(@YO#sMR}kJb+B<@HPC`l zArTaQWtpJrI2lxngD2sjj@N_gg}5G6-ovZ}xdbW+D>1;XLlY~?k1vM`L5(a1cW6l39|I3i2~pG&MN`6da)X zD!v$&IU!Tfh;AozXgw7?0hj{Q2O3*P8jpty7el9*cC zTp(+amOFq2sF{q>uNlh&BPfG)} zKESnT2&D4QVF*dBC;<}+j_~z!5I%e&IwS);6_o^8z5^Zw0k4uOO3lqL15H1J6y&9r zg9>zo%wo`Z4MRwNdU{SOs0CM&ky@ls4sI={WmbUdVCc*^JO_dO0ZOZ&xpGjY17gE7 zuO4=@ib3rskfphanK=rXX&@^Si&DXJ@F4w($t9ox6G*cHW(G9UA&vvB`v9%(OU=sw zt>XfBxL^v46>`C&2-xL7=0h4^nW;qxEg<3I%$(G`WN<;72C6YqL2E8x_LXO(fXeT8!FFOx3kQE9p!W1$=11V*RIaUnt zg&+)}ps^h*1!yZtA=*D6#M9qTPfstFAuP2hJ_)o?3A7pu)TUwx%a6|~%}upp2u~~m zEj?ohPt8fr&rOBVpynv7_frh2DP)!?B&DW7R+(`TLu2_0Ir-_JwX)#)55xww`aqpo&V~S(75aAgeQydcS`q$ocJ?8e;Gyi)Ld zmlZ?2ODcGkVmx#y5JNn42?C^9#}MxhT7PWC5D#5V91lw1Rt)iwA;{#!;#7us(6CBs zUP)0ULp-QY&k!GwT2!2$XT=Z?Ta5)`7NvrVijw^NoRZ9fVutvj#FA7ihWH>*7b89> zwK%neAs*aXw_=EgwwA$-NH0n(1JR%$Vn|dd$;?SfWk^g;24VP$ z)kN^J(Zrmh5{AUQ6o$mS%v>-5ZWb{l7UUO~6y+CWq%tHH6o4>%y=WqMy=Y=lIYVLz zLt<%3KA3>jgbbiWQk;`moWYQklbDw0no}hXgdVbSb(bq6|JQ?Dd565DOI63u`Cr~P%(^OlE;u#ny#Bvnvznh=Hw(YBq!#8a4MJpulxjcgFp<0RPfSII2W`a0;H;pAsMm&G&!-L z7&LjF%>bH804>e~FYIGTPReIUPK6o|S`rFc=wHkLZX75iK?G31= zfW$!^KuEuUAvr%cDIa2Ser|3eLvle$9zzN!hEfts7(k6kg;dDezm!za>_jmGY_25@ zyqXTi%LFZ_1C=WbAR<4VAtf^n+>er48q_&5^x55T|T&h3~h(N zS2SW#1{!DwuRcOnl#`QK#E_C-!jMvwSPmvY1$ZK8Nn9#4f2D#`Ff@OqDnRlUD7-)| zQijx&lB6Pr)Z8Qx1}{GYcb_2Z&r)*>N-7z^=^9+XW~V}Vpb&ws^9D(SW;|G;lHjjpM?TLKQNW`TV$s+OQMXb3Y8)QAAPQlTWDAw!`=Ay**>wAir(G9j6vn!*4Y%>>z0nv=+ok&>6r z07}NtbP1v|K|-1786baT!?o<}hTGbK)FUWAf||SF z9Xkv;;OV{`$aEhhOmdQP7;;h*%Ros4+>+8`0F8SpB<7Sr7)eE-y*gkq5HmX!Dh}#& z73G68rp9v%f7Aeg`h~;H7;pVQ&YffczOg$fC?H=X$fLO^n+A^W&%OW z_VY?}lTwQq@}Vg!A30^^LsM2hXnZO^JCz|HYAAhk## z7gV?~fL3gSGG;+~QeqK9L3#;8L1s#NW*!50&sZ@-K~5=z0F@Gu$SugrVJOJY$t+0) z?SX=pe#^{kcz|xl@1U!u;Ky21D6jFCZvFXupuP`n5|m?niT+*LXf6dQGR|2 zBmsd&2~|@VAQY&l3+EsW3WKFVWp8Q`Ls3aV9z#(%s8B9W1Wmz$rhvdKaE)G^oK(b6 zoLrE{Pz;%<0!1~H37Q3j34@XqLveCR9z$_za(-S)F^C2?|KUMYoSK^n+Oz;t0!nb8 zO;g3G1w|!A4883$xy`;=M z25^sz0kTXS-q8oI2i0RJE&waY%!5UJF=&Ve5`M)6IiLV3E-VFg^+DmvP+XE&1R_Ay zJYsx`0WxY0D)1oFqYTBM(HCg@#R!FG%m6CVK~uA!;uFNlNrjNeV=j;txQIT8l}a!MI0r#eF=z^g0YqfxCFU@I#(Kd7qCf`; zu^<)ZCFwayC3y@b8TmyZvM3ciQ&m)wQOp48MS!Ou8A>t>7)l@`Fp#XkP?8VL0ib>m zxMT-2zzT~}8A?Ed10VvH=~KW$ko8s!B}HKGRFp83Ld)V(aU^`ml9p)!yp1d)KG2L@<~U7nZ1PziNsWok|VLuG0nLqJhJXicWBXNqoEYEf}! zeja@6f(tV7qw8Coo|&TSRGMC_8WS2 zSDKlxmzR&wZKaTx$K~tk>x%G{p`HO3Xw6w_UWsl)FNHiyySe)7CkEki=@mFu7DiSV5cr<9d@ymLS6xwTWo7&tpH)# zYUC*>+A0`oT5~Zd6clAQLo@ zg&@pC@D}s5%pB0NdWZz5iCu)?7H4Or<|cx6S0h;Ypt+RnBGA-_YKj7a2idTmUr>;C zcn7#!4w8lQAa*5|fgFiYqfnNZ1KtmgE|FLSmntaA2M<3amMNs`8j z4B0&n<$!u@s-T(hB2e%sfM(}%LEFrAK~{noFatmhHc;zAwOFAzGX*RIs;9u)*`cAr zpjxa8io2p*&`$KEq|}^}?3~PO*iQ6<)Ep?+KmidgiAA6d>A~4WnPsU-pxr1&dJ0a5 zmlc7EW!R>4$Fky_(h}_Z(p^$ZN>UZdGIJCXA*xcrd(%rmv#;*8@xfA(X&D22YAa? zQVwVitQee7VY{q-DvOItDvPpHVFGTTA^%KdQ(-c}iMfe+B}Jv#*{LN8*v#?{G{dTXAM~3EU>oLO^i7K=J|1u8>4NTb2r8D@Xrl*7RVN!l}Zfa3>svd)5Sz=ysYEen50!q?C6^}=xWXKlx#G+i# z7WY(z?8Nvy(9k7lTRX-U_slZL9{1v`d~lVVUX+;25RjPz-Q5oAu7stgsf$wcFm}7^LZ{0Tix}d)^NUIt;Mv!T!8;E$W((Wv?#kd752}bjgGLI) zC5b7Z-R#K>-ibM>pq3Pzk&z1CJ`d-EnkISa3_*#xxv8Kn?#1!oCckqcxK|6_$qw3a z4m#;VwHVAzR7gL(vDF-kH zbOSsno)dGpTq;XSxIFXH6B*$02qD+Jlp^pLxD{x=wJbF|A3R}@!{At!T~rCqti?(B z*~Q3wL}Ab1Q<|O404@p3QghN%ix|8i4Fyn$W1X9@5s(d1$CVA)4`fx5+JW<=A{>xfQnE^l>n2%EI$a!fQ<&lG-Tltw4%yMElw-~ z#TRmoRSX(Qgzs;Ml*e#|x^R`CqyaT7H9ju|RQ!S6s*zfxiP%67s+3ZTz+)4KcNBrL z0@SI+3Q0w!*@;Cc<%mKV=vWcZrj0~!VC7YofVbKg<$#x)AKp;}T8<2gDi|M{NrOv} zf*3Rqa(G9P6@zPLIw+T{1vtpy-UUSk zC}2Q)|6M>;acW9tIyf=-X66-VgO~XsYW-qxg#=RT1R9kGm6_1S4rn=NKFA`7gY`g1 zZWMtw7l2!RsTqmICE&sv6jUy$us!!~`Je_91B6Q90(lp-{0me)l_eHIH{OFAbucvw zuyqktsYP(HY*5((O|YQ3H3bGlOQ^UATvi|nWM=2*ffn$TfwtCz&u;KdEGS3?8^Qo) zrh$sp;GDxtL1ig;+dVk7mXsF7gLd5~F@$A;R*Zuy_C(OMUtVHKW*JBnbbtY9K@7-F z@C*cKp)I@tQCyapmy%eTo~j2`iawU2Up5VqS=!}H?f&zu UAVp(sB$FEKX{ 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/oc/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/oc/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..c313a70f9b556c7687601662e87aa4d21a899fe9 GIT binary patch literal 100378 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%0AA(|+B=vE=`Dc66Unh~hvb4zH7u!8NG;0E z1kLe)mayk#m4cRpGUVsxm!yKGq#)OXCL*egM23vR3y<`sW;0}hhLkgt6%rXh4Jh!+ zFa%2>Ujd_S1$9Yg9(ZaguY@5p4}2OOqR0WWia_W4L0HgYhaniWK`J@11k`vd%LGk} zz?v|s#h`IsJRM|cQGn=;Lj}-E4W!mTj*c=^AEZn{7>C-`FMw2a3ZSFyQ!+uPvXrDE zuMh;)L6C+!tQLnF3pWr}1VP2otb@rCvWEd&g24?1g*0+Xfo4avvL~T z+|*(a4KfV5u!l4s!8fsjI-8ja`H+eb+*mBh%t=XP0A0BXT9^u|Xma!O@{7SIpo99a zpc8>m@)ZNJC^QTUOH&~iv}Qr7NYE58grxv&TO>l{!3|Atp#xe2Rhm^N%yERflq%L~74oMr}gq&ZLhf$@1D(}2ZP;;X=A5^`A?Lult zK;=q{U>2gvA!T21^As!#x%(TXSAsjp5i&9U51du`o#6=X|ARZ`{ zBc*4M5XgBb{S8pqfnp9-5ELH>TR{g-z#0m03*jN0mkFvyK*!XA*Wnc4oX z+Clna3ZRy4YBJ;mgM82q3e-?6g2{n)C>5pVfCs%mtqE}N2GObj2^HjnPrL%pkbnxc z%#uWK7ds_CsU(#FbOhk0q7v}U6`)<2pxK3D&~zW7TtZZJ;4uzJ!H=b`D*-LU%qxKo zg+P>n+n|X>$?#+eIqnIX!odXwqP+~!0!mw;c{}hXAh?-O9grLVX{&?BwxLWMwGc!W zv#P_Z98zO}wSw-^fOxtHbjB^{ka3t#z%6{Zi%TKHy|4`&D3YK+2ZsZ+(+};~LV4i9 zA&?S8mk1&Qss)M@^NMwgK}(QOd7!2(c>DyRKmpbc0S%p?sfJ3y2Ut{#QF^K=>acRR z7<6Z8X>tDH^(mmKI8eO^?Q(*9k+5zkG=oB=z_AGK%|m^LDUDuVfS12w@3})Y!}}O8 zcfbX}K?&}Z!1^rcTEHquuo9ZKic3?ll(x7z+BKwFs!8t6@Zsfn57m<{}-%0B@t0Ffd#+@Lg(h-MH}2mObPIS1*l|7 z0Tl({xp&Zzb_!?&7t|5}8w#?eAhif|{|9(iutI7ccy2PW1Tw0Q;DQIc5L|F00^HgF zofQq*K?KtWO7P%l0$p~W13u^z)OUrCk3odN-75IdCvusI+>U_Mq_89mDnudWIIKQECXUm>*ud_8$7(l`vLiIkWODi8DWp*!KLV2cqz z3vNKifkTg$D?t+nUjhk|&rK{z1+R?&$FVBtJ`2zpQs zHXX+RJyNSUHC+$EhMnRBT1-G-*%Vwqk{q*=AGdijgV*Ck*1un>mte~P!k;F zxuQhSdK*vx=Ylo}fQr+^^rFNxq{Rc^kst7>rV4}|1UWVjQ#Yu%AznLjIFMsK7X8FI zAQg0|Cuo#CwMYT9*8r4*3ySj784A)tYgIGB^Xt%Y4A3e&$kaY4_z*Mus>PtZpIlM_ zTA5P{3gDv5+*HI;{etoohQdNBL%cE0c2ce33%EP)RO_XoZ zdC8#FFHqG;%jzKY5nLR+?geT+(pVlsJ~0c{gFs*I0#}2))&*)5q~ZWArUdO%Vo1!( z18*EjO3X_EEkRCXNXksg$%LM-3JV4WB*A3RI?#f{YfC^I1oHDrz^8_TCW@f*f1uTt zpyMBMN{d0a(k2%jUXcQtHG|N_40(q)l_Y|erX=PhLO7s9|% z_yREKRxD6=8hU<7K~X-)j?z>H&?XSjvR3FhM4+LS5{Unhj&^{YP^AD~V+tLTPe}z$ zd!nq-gGfWBesC>qh03Nd6y)U;B_>1H(ScTQrxsVGmVnyD;FaB=xiQeV0RwnNDs-d+ zl#5bQi_<`w!8B;M&5B}B(;c*MPLH8DIXRC3HsB1N+JUW~Elw>cN-1JMn(zQGoKXO; zn*r_22cO*ux#}npd=NEgJMN*~#OXjRr~w_8MU*9}DW#ynaAIvJNCj0~kp03SJ)qN1 zKx-5cnG3Qo6|@`yK63|}l}t`#$jK}Qbz4EZl`=s$I4P)VfYwfd?lIMbU6z-e555Hu z(k+2*hJmgo1T~9Oz}J8z=77sBs5GRyXMpT@&cVCAP7hoxrKabAVy+;u2zscV56YQw z;Nv|(eHqy4NT4&{ps5Ykn@R;8j{@-@XhC!dLo)b;8gPpOyu1lij3t6v0nX47R0B0J4HYvB#%KnC z*3}mmA)_01_R$p>FBU6jiJI=`V%fzAira{xPHEHwvN8lh4FzBnCxh8Cp8OaY&) zkqBC+3ECH$Q(9OG+SXLU06se)DNi>wg&`?V7gQ^Qb_9U8jwU9TfbMTi&Ig^e1zJ*_ zl34_q)?xrPw^BjVW}t&9z~@bKqu3I+Ags9GK4WO5l{sHUfrJt zx{wfj$9+a31LCH2hSapfD?r=9L1%zMc1pqn2DHos)Z|hChYbo3=6_JH3wk;oLn?Um z8#LPt%DbQv1vWAZw+>vQ=A`DOgVq#4a~Nnl7-&)(aq0yu8o*^0sFw~2Uc@0X44_ph zsVNMpDY|({45?))42hsaf=UweKn=3|A_mYjoC2z?ptJ$1xS;pPgR5O|OBi&|HN*n& zVq@@RKB(Zz1Rrt_nrQ(QfeZzZJ32wx05*vVav%I)J5&XT#n+${TkEJd%Y91&N zLHO{v2RArU8Nhqt8IW$NgAC*(f=7W$GV>1aVt}7m4T_)wP?Ng^RJ$jZfCnpc7!buD za@mrX#E_Q+O5J%$pwtbyf*s^o&=z=Dek+2F-GDl^(DS!IhX#UrH}J!^62V~tp1}dd zF%lP)H5nj_i6N6#;1OgbKSTHkKO--NgL!6!%Yz#Uuys4&<(tKz`RNh{&|U?| zL1^&t2nNW>QJ^#Z!BgKbzB;N(Y)NV>DPG*2!nGQOWrLZ)ysH7M&$F3_=rkW=MBMIdPX5x9i}DFY$LQl%s^z!|xDrJ&u!;MR>oN-C@mm{^ol!~pA! zswWmDwg3PC literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/or/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/or/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..f7f4d6ca2c82e2dff1e29b863289e823f0dff615 GIT binary patch literal 47589 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pa/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pa/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..4e5543444a1075e5f5f6b79ecebb55de752a90dd GIT binary patch literal 70778 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%0A%I2jVc$ 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pl/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pl/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..19a7f47c3aec32abe3b8d3b5714ef76cf96c3b6f GIT binary patch literal 137893 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pt_BR/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/pt_BR/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..e0e8494937adf17817c49d7a3cfd1703d2c385a2 GIT binary patch literal 131984 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 y)#An|510mAp607-v& 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ro/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/ro/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..429ac1dc0417be08e66e29613ee7c2af1a273fc0 GIT binary patch literal 135819 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/si/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/si/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..260e1dab6944b139d6619ff5f55328c7192b208e GIT binary patch literal 6577 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 literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sk/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/sk/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..5fc00ef4dc944a1c81ab24dcfeb70f574a2521de GIT binary patch literal 126237 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 fj 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

  • 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 B!N>pr literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/be/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/be/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..b86fc3a92a4ab2429e722dd44a03931df329598b GIT binary patch literal 94425 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�C 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 WXqrID543s-x=?f{C_FFhU;qFkw^cF# literal 0 HcmV?d00001 diff --git a/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bn/LC_MESSAGES/cthulhu.mo b/distro-packages/Arch-Linux/pkg/cthulhu/usr/share/locale/bn/LC_MESSAGES/cthulhu.mo new file mode 100644 index 0000000000000000000000000000000000000000..42b6d8514335690b9e27c935c2bf093e3fbe2487 GIT binary patch literal 118083 zcmca7#4?qEfq_AVm4QKqfq}tBlY!wr8v{d35J;4P;YKb40}lfO!_8a<21W)3hG)49 z3~mez3@>sS7{nMD81(ZP7`zx57~Jw07z`K~7$)X1Fi0>kFdTx?xAPbn_!t-%zCdZ_ zd9g7^E2( z7>?yLFmN+4Fg(g)ddU;oD2*MTM8iV-&X)J?>dxz237yH0OF3nQ1u*z3=FX# z{}eJXC^9fG6cjQr@G>wkOe%z!v!IZHL6CugVP_#E98VWAFz_=lFx-HOzksU$Rmi{~ z#lXP8Q3Ua~auEZAECU0BRT0F$5k(9P@(c_NB}EW(rxZcduPuW3_e2rIp4(9UZ=w2G ziXr}0Du%erxR`-~nSp`9u^8fi*J6mfe4*k|Q1Q581_m|;28J{!KereXPNl^R4C)LF z40Xi}4E+oY49kik@nBZMz+lF}z~EE@v8NJBx0gWFPc4DCZ*K`i{rM6G237_JhTA0& z_dJBEe_F!8pvS<#@VNxyZ>3U*Iy)%sQVNMDuTlmEBL)VB5GcRBlz~AMl>SN?7}OXT z7?zhp>^WBoiN{+|{Vz))@%J7o{;L$?f6g)n1{($j1~DidTm}iZ31yIQSXc&e|B5n* zJ-f;v;c)><-z;NbFa@Q@GKl{r$|2^el|$TN4CULGL(K6hhlGDzImDi{a!7hDFNfH- z0IF{}l)t$gl23M(L;QapYR=7ah&x`FL+t$mwTGz!;!b`jty%#w*SZ3t->Cv(zfT1u zABI#gFt9K%Ff>BN+bSUWxeuy;e+49+U9EuF_o4z4jvp%^;rjLC7qPzQ16`#Ok!{?lW*9uiJF>LKpE0yXD-J;Z-M>mmMQ zY=EQ>(FTaSv>G7k%Blh4KJNxd_(wHB+>_7%Ntd||5dTy*K-^o`0Ey?;28erRG(hZM z2Bi-{?YY;$z+eT+rwx$&s@KTCpv%C(5ZlPWV8Xz_(A@}$=L3xl3|b5f40jtL{^n?c z*dqv~C7K}i$TvaUquT^YFP2S^ayz04Vt*}^KeGwq?|n@We;kAIFE>HVzug2WPo6-{ zeF2sK)&z;ye@&2dBGC*fm$aH07{nPE7=oa5Rx>1?o0=IIG#MBe7BxfC&6#FMcs^=| z=>H5AXKjJ#mu`W?gK-NaUfo+57%UkW7_wU+;lC70Z)t&q?_sFEYb}s;{;mZQf9$Og zcgnOv{BPFEz@W;&z!2REN#~8N5Os^7^4p>Ecc6TxHb^+Aw?V?wpbZjEHf<1hc(y_O z6Vb-Nkix*gkk3x(k|@~^E}%j@fQjek73C{8B)%3v^{;^H-_j1TXE)TG^X-uId8HlVzFScG15`a*2gF?74v0JCJ0R&x zy9451j}C~wzz#_KrFTH=ZSR2iyB|u=gVJj|Ao+1m2PD57>wwg^*E%5O!Iut*`@}jS zv{om?e|DXa_z8ycb2}mN*97Iy?u4X=4N&?7lzsp;=Lb|hPZz`<)h>v;-Mb+5ery*c zpOF{b!-#&!Ou7L-|tO5ce8&L&C?c8)9B^H^jWUZiss)LgiOM z`Nz8<`RoCd{sW~YdLZ_j^gzt>>4Buj%pQn4`gxI~}s27sXcR}TE_d?A3)eA|df_;$qHR*%6C!`M|Uf2f-&nbNn z|80ZHpNG5{^;~W(zO*-+_4`L-=0wUI4GS1)nC;QNk7d{ z^}YR&d@vQtUj$XRsvlzS=6*?l5n{j4M2P?7Cqn9Vjfs$QEEFnUKM`VI$3%$! zzKIb1^Cm*qCnrV>u^`FMTpwGa-P%{nE{#*m4 zA5DX_$0epi{O>;<5`N*+A^yvn4he_q=@55Moel}NrBLy`Q1R;+KFM;w~XF$q;le$gyQJT%RMgy*VRkoesML+lfo18Jwr&S79MWME+M zn*&KF4RavrWaS))`m1vw=JU*jsB@bODNicqLgKM)F2rBc=R(r={JD^L-7^;wju+=b z!vFbPNc{Yp3vmzcJV?3{htgW}Ao8~J7#KW3{qA{?_?tEll0R3?gQVND^B5Rx85kIT z&4ZY0F&|=&|9nV!kvgA&A(DZCp=&+^gDV3A!;|@t_NLYXNd1ty0FqzZ7C^#b*#d|^ z)-QmB=Ya)~^n76f#CYiA0VLiy7ed;rVo=&;AtXME7DC)vz7V2*)aPK;?K+_kaSeK1X9i{gsQ)|1d?9vEP=S| z$r4DuW?2fMm6k%{(_ty3pB}ap;*ZXy5Pxl43bB9JQb_tevXp_rmw|!d>r%-0lJhc1 z{Bo}?9!a4cB?@pt_S zNV=a2rB|+iv`_Y~fVlVm3W#|>q54EtLc&9SB_!Qwu7tSD7fPqDgoH!wN=W^%WF;gY zom&ZU-*2eA!YW8OxUYh^BW@KW-;}I^_<#K>hDJN6cK;o%o4aA*YYZw@;85kI5LB+4Ffu#F8Yar?H6;%Aw8i;>>tbw?X zb1j6gw-%z_el5g2-?fl*61x^+e;QOg8>+r~EhM~q)E{4 z7#K=GpwdO7GtY@#k?UePJV{oVd9W5*{x$Lj3=2BP2e4Z-j&!>n4c2)+UH~7MmdMae(rD zH$lt|-2_P|aZtJ#N_Rl%xtk#F+XU5jc@reP+=lX>ZGzbQZWAOw{MZBuKjF=gddzGy zBt6A%hNQdN&5-b0wHXpWM>a#$zupWfKlrvl+!X_*Q=xR;7D&1;-vY^(oltu276yi; z3=9k#w?O6#t`@aohkHmHeEx#R7E~ssX z#G4&d+<801Jg@B#e+EO+~Er4 z`|N_aI|QmOb{E9{#9a`7mpXP2zIy8gwU7+%T zyCLoi-wnwpF}oq*)wvrI-?Mf@+I3rZL;Q1TH^iNfc0rGJ(oF?SYu%4%P3s2NE975Sp9|H$6e_+F%HIN&-vQ+xfV$%d)V$MB^RGhPdwUP0e0d3#XWt9) zhu~g_zvcHr+^e}4lCSll;!b-Z;ot-12SW8l?}hj~6DnV@7ZPrzdm-tpaxWwtTA}KC zq57umg~ab7sCnz5`gcOr?b{0p=c7>bu0Z)W_CmtvIaK`9UPwRi8-It1eRUtiy?6FO!r{R_NIH7A58}T6`yl@2*$<%w_d~?R_Cx%o z4CQM>`4;;j_B%jn&;5|_4B8K|Ct^P&Tw|c(`A~hOQ2AP@c;kMEd)oIy+%t7QqZ!R?t7?vze4ph9e|j}c>v-*0VpkU0OC&xsJ!X{ zi2rpCK>T9}Rc8*Rt)cSv2O#m|0u}d%st<;m6L|meB1DL)&b>L(w7q?_qb z^Afi@u%QHh`Zzt zLgG*DAS68W4?_HH45cj&Li}%g5RyKfq3VL5=7d4@Cm)1_YYtRhG1UB~gOKv6>mZ~( zvlMFH9;p69Q1i}1^<9SA`v_|8^MjD^{Q#wZL-ny8g7`!D5Trg=I0Ok-t3!}{?Q;mC zFAPd2LgjOy{JKLBe|H{&_;=DFNc}YZ5TqZo_7G(J=IS9x|Ay-@r2S`m7}7pZJ`7RU zdl;gBE0o@K7-Ii^sQk&pkZ}EY7!uE44@1I<@d!km;|PS$1EqzbwA2xZxr#?1?o>Mh zF<1Wx#9x+2Ao1b?<$FQR3x$eDLd}Uk0%RQwxM zpX4z}_$eNPn6G{eqF?72B%hfbgVeL`#~}UEl4Fo@()m#FbH^a*?e{T=|9Fo>^ot#b z_*3CH#C(n85P#|&hq&A5IK)27?*Q*96M9KLK&K z#|emk{7*pq8F~T|AMsE+`vk;42J^?BJ*Fnua2vvUuO5cFWKY{YUpMbcB z`6R@B5+@F-ec8Bamd8^ylGBj%z3DV0 z{cJl8@yGttka5VPry=G3cc^`QXCUf@&p_0PpMivn>=}r=4bDK!F@^H&&OrR(dK*FE>EW|uXD6Mf8VxBpa z?+&HIpyH`#A@-J@g}ApFN>78zuRIGecPEs8`YgmD}%e#Qb0=Kk*#I{blDM?w)WC;=VQKAm;8l2XV()sQ80(kZ}HR4&n~>^APhS&qK^t zhtf9ZA?YOWJfz%6KMx7tlJgMvG(g4s&qM5+a~@*fn)49%?1h?p9V-76D*qKqvt5AL zFMa{yU(E{;_d7x9I4E6p0b<{@3lR4#y#R6V?h6q2oP^3>y#R6N6Da@V1xWZYT!i>n z;v&SI`WGSk?Jq*gQQwOY^Aj&Z+*5E7;*X|_5dD*(@~baG%-;p&AHN8({~DD42ugpv z2=NcYC5XL}mmuM40Hs|oLF|dT1Tin?62v`~mmvDuFG1{Ga0wD`J1#-oa~djs=Muyp zU!eL}E<@A_L21>?kZ`iN49UlSmm&El^fJVrXed7uO6OmOL?$^2kvCr@d#GTeqb@ots_bZTgfge;~Ak@4lC_f#luiy$K97>?_RZzP93M3w< zK=})x=B|b6+j0dG-aDZ7o`9Nr0V;p<3IoGxMh1qvS0M8$o!21iBM)DL^sA0ugQSCZ z*C69Mtk)s!L67T@@}}TAq}?&$I;0-h3Z*Y!huHh^I;0=Rcmooz<~Jbi4c{9O`KlX` zbklVMk`5L_>1{V4?l}q7$9xmg-jTcsQD+0C{cl3dPrAtfUT-(!CS;udI8^=Tn-F`% zZb9r(y9Lp2e+!aMgKk0cZ5EVny9G&Si*7;cw+&GG^eqO4>!5X8w-^}W7#JA#-G+=q z$ligpo2~9Z+?RU?qJILEKkp7?ob%uvNV)R#4rG4i{~ZPfM+OE4yStEar-r+b`K`To zA>;91?n35uRPI6MRfFz9{MUUC(*NCc52F9!JqCtA&^+pWNV~oCJ|we;<-guS5Cw?nBb=v-^;Eet(~Vp@5NrLHq$ETss~@#`(59gv7t{ zBZ&Ww|Wi<*Yf9(bh7L@#9!N~{3Z%F*F_zj8A)4w6^m-qvTmxe!(`eoK1NVqQj z1JQTm55ykUzmV{?{tJl@*T0Z{dcFJQ;~!*wkIjDuhBDB4@Ba)8Squye{tS!^ z(-{~Tb}=x5*U<+tGBQ*!FfhzyWCX827h+-ruWy%u(iTjN;B|;0OpM_5?sZIz;Q4|s zCPuKiKcV~rW(fa2Gb4Cidl(BNc-?*+3xuD|!pHzx=U&Xh2wwkP!@>wI_Zy({>sc5X zKh>?N8kDrmDje&t7 zQGk(QE@i4|f5uQTowVg#>`ULge0e_RNn@3IghxIB9%1c^suVTibcFe7+=Fc?Zt7G?zR zC%7!k2wr#aSeOyK{#HeV5nSI!ia_Ldh%kcJ4V@5y`0tAd#5_+?NcxI_(rr+BgD50D z-V$X5@1uAk3em?a#t7c;kR-+k-Uo01O22^80^*F|eE=5XjNo-m`QniDu|gb@KAu2n zDG5gKyk~#}BY1ts90^Ezc_hKe;K9JapeV@*F8{J5A^P`9Le&41WCX9%ca?&qmnJDl zI@u}(v5#Gv5xj24K^kISvoyr~L(&j=4jG7fjxrE^wK9-&bzTNyo}4Ts{RGM~g6C}~ z%RUR8mmI|m8wGGbA>7-U0i_Dk5w7L>*Bvb`BG|-^sTD~ zalf+~BY3~XR5eEMzLz~}kaFgf8YEp`R)ds3pVT1f_!pGVt`1Shug(bGpCh3Tk+)T6 z1n(R0QfCCOkIYqvq+d=ANPd;nfTSZc4M=&FqXF^H91V#5S2Y;H`;Q)LK-~351Csxg zH6gUKCL?(NQL-i@18Cz@i6$idb7?``W1zP0&eegK-=zZy=UF-sd)Dee?7yYM2wpe!7)tBv zLipvnj0_Q=eF?gZ;C(?-dXRXq(1WBCKRrnLnyUwK*JC|MxUlInG88f}Fxcxu>Wz*1 zj0|B63=9ee5cifFK;oyx0AhcS0VJJFHGsJDyaA*fxNpD+Zb!T{U<9x84>W|7WA%oR z`f7tABwwB}WCXWsIE^6g%{F3W@MmCPIAR1Te?*KS>CM3y5`V?U5dDjx^nPQA|85&I zGL(brA7e;4UuXi!SD#EE<(i)<#GbWKn%@lKzCtrbhDOkSH8Vzr0?@j7b4G?P1_p*R z=8WKWbGQW~LpuWl!yOAq{gz@0@&6M`Nd9|c$;bd&Z*O4*DM#Y0Ansgf1u54qT0z{w zVGYSwDb|p3dWkh8y?wNXQt8cOp!LGqEY6C`|sogn#bniC{lt#^WiCz~@Q zeepR%_|ndh^rZ~t>p=M?&XDl3b%vDtlbjjB`}}S@L-NNnXGpsF=?rNvsJcMX{Y4i@ zK70I)sK>apfMuwvd3=D65A??J?evtI` z%a0MCjL}Jj91GGE8P*V7M0wNoPf2jNo-p)4~`T0zmD{Fi5_Y z4~LWk6T%r8Vi*`0)`dgji#q~RzC}bp(o=N=Be);j5&=o?Pa+`pibg`(xAKt?fBQv3 z!o38_pBo9O*AGWR@)uJSM7?bkBt7OtLCiTA1xb&mqagM2wJ1n>l#7P=-z%Dtp#!up zGn$cMA_D`%-)M;Y`ePvJe^U%3eD=pc+-VsLp=ZWI%Eh0tkn+$o4pRTt#6i;8k~m0s zZ;6BS501w%GJFNC6N-n>W(kmXm`)<39P3JCWN2kzVBkt(WJmz5A4_6nU}a!n_?W~9 zURU`&2@-Fv$&hyE>|{ppzO1dukb2=kG9=#pQy9Vfp)yh+uiOknpQ1WMtS5+Rt1FiTCItNP8%;2vYv$7eUmQ7eVqtdlAI`4MmW6 zxKRZ0H*YaSonef_HxlD}fgAo0AhjFDjiXdJ7Yk>NiB1H-g(NclXif{|ej0|Uc@ z3P$ig&)!N%{TElo$Z!X=FRuy`U-i|H`md)Nk`9hlL)sl|HIVchUjr#W`)e2(<}olZ zT&sbEM` zQ=oK58zddCX@ist``aMtiLo6LFS6~BcDyf?Zf=K!=gxLWc)n?exbsUpBZC4X1H<2T zMuz2}{luM+a6Z-vasTB`NPYGON`LNzl;^)X8NufYn07(J(W?vMo~SN}zjC`E`FcVZ z#J|_N7#TqO@4t3I%1eQ6Nck4m4QV${=!WPQ?SZJ%=z*B)+yg0>f_otOsk8^;&$&=~ zXAdL8GSEIRD8Hr`QvS^7g}DD@FT|Wjy%6_)>V@cM?}OAw%6$-iP#>gx$?JopleK-2 z_TaRJ z62H$ULGm-#WQe@VWQh4DlOg%RZZf1E**O_fZ?H~*^ru6nK+2~zQy}^or$XE*Jr%;2 zp9(S05=whcg~VGVR9)Uwh&1Wkjei<$LDD7jbclJ{(;?>RL;2>@ zA>nL29b&)JbVxWyOoxPH>U2mutYbRF-euDv_HLUFiT69xA@2GE<+IIz#HZQ}NH}=U zfanXD0WmLO2E?9bsQAno5O=Md0Wo*&3`n}VJOdKm&t^c%V}_X!{hBi&@#ZrVV(yHY z5cMl&LgIh-Oo(|mWxbKaN=A@ zK3qH(;{LO9A^Gj@T!{ak&4tw8obw>=<(~&BhlJ-r)Vt1u*dIC%;_eJ6zi1w$-`6@1 zlHPXCgQV+s^C0fFoe$CPH6LPb)O?6|+JsCY9}e>;?(1vO{w z0*JqMEr8^=_fYjL3nBVB7DCKZS_pBE`a+01v=>6$ZMP6ozl1==+o9sK7DB>t!$OGv zcR|g$yb#ilyRi@wFFzMT;!kD~B>wakLHH4iAn}*A2x4#XB8WT6p>)k6NVqpHg4CB2 zq3ZTQ=|hVk?mPyiZ!Utw_nSo!_sA`VjN_OuhO`q37DLS2x)_qKjxL7S`*bnH{FjR% z{t;UOsizc{FoMs`uwDX*AO9tgbXu_lQhrWd0%^Z(Spun#|3dW{FNLV{gVNbcA^z@I z3bA+7Qi%DNmO}E;+oh29@Ry~K{*cZxNPA@KGDe2^pnmmoi1?4?j11kNb4FG`Xx^2O zbTV@#BpjBlgoO9bm5_1!J1Zgn30?(pPwXm4xKyoz_>#kV&8@}ko2@|4MhJ5DF4$M zNV}S4EyNy~wT$3-9K*E`|5-t4_qC9G5V95$etByl?wq(5;?E^(A^zC17UHkdYa#jR z5>y@gI!HK6t%H<%D(e`*`I_wA?}{N z6_Rh3ZiS?W16v{CaAhmRU4OSi@}<-^NWQe(2FaIA+aU5gp!C&k5OY3lgS4l4w?q74 zyB%U~>~@I$!tD_IcR|IEZ-?l+y&cki{I(t9Kb0Mj^lY*N5}#2!AmJas1ClONcR=hf z-vLQSQ=sZrL+K4WAog$F0clTOh4LRlpsN6B1uGJ0a=Kc_(Ci zZO2Z?IGFSjPAs+Fpn`Hc&bqN;mC=q}Qc;A?6%|ieH2Bf9{2hZ*uN~=#SY4@mKvmNIGrV z2Z^7KeUScd-#&;rC-yYn|Oak&@!A@!2w0f@Tn1Ca1TZ9NEy$N2{#<<*XZ5O=&i2ywUkAxOG4Is{3V5r-i0 znh&M>4?+B~{t(2T+fe%BA&7qV!w_2PFeIFH4@3MFa2OJPv4%Bz_)1&3OVf=i^~WJMs5nh&#=XK2%#Mkws5c3(1 zLCjG*2JyGSF-W-ELdC<6LG&dagQzcr%1?)?-w37mLDii;2C@J4F^K*5p!Abt5PM%i z%@IBhaku4hNVrEr>6+sZ`{o~qxM%%wNWAZX%6~i#Nk1YdApI+Y6OjIX&oCcLdx6blaP3uev*+vmXU#B8&v<5QxNyuI0YGxdwL4up3kQs?InTJkZ|%i4YAMf zG^D%@It^(Dq(J$7ry=$(I1O?C%F~eivH_~^_GyTJ??dVLry=q1|1>0gna)6H)iaQE z=5YpMU*Z{v{i$al?#hPJ9cLi%v-Awa-$&0t{Cgj&@6#DbKkwTahl`ISlmW&|NAh?_fvfd7~ zW(U-c1)WgT4HE;yR%QkUOVHta3=9k#pzb-v!oVQN%D`|QwC5c(AH>YSaD$nFp$lrC z9TNk?CMX+Z-Bu23;lwhPR;eWSAHjrZF)voP^qakePwuBuF6x1H*r)zH&we z1{D?t@O%?Uss-u>5F3WmnHd<`Sr{11SQr=t7#SGOfZ9+@3=C(%YnB)o)-yxaQ9fW~ zV8~%%V0g&Fz_5>zfgu^{kIyU&46;!Bw4h=jvsIZH7z$Vz82mtC0hI@dgYXY1|2QK9 zgEA`v!$wBPTH6vP28Kdr28Lry3=GGiW^phvFieN~k%@(YVKoZ_Lm&$S0}s@UWsD3A zZBLjmQ69dCCCI*IhsF~cX3=D}( z3=EM>3=F+cI}=$L7&bF8Fid1(V8~%+0M7%~K+W!BVqoY8#WOPl!%wJs(EJ!^Ec^u2 zOpx6m%n6kTvD=_>QOpbsPRtAp>zNoBJ|oHhWrD0D1F3~!TV@7^9gGYN0!$1HADI{! z@}TNjp)^RHC@TZQQWgdVV-^MmDOLuCJg7UbF*7h!F*AVIb}=zBFgP$XFnj@-#md02 z6LfwlR2}H-0+2Z~m>C$3voJ99FfuT_WMW`21f^S$1Sma$%m(F4CI*IMEDQ|WSr{0^ znIY>;g;*FE{(-`Zk%57gnSsF^>Q9i?*HAk^>>Q|@d08Oq0)K$YP^f%83j;$t6J*_C z5d#CmJdj#e1_nMR1_pUn$T~%k8M~Po7*;bgFqA;!9wf%b$iR>RH3!6p;Vn!I3`ZCk z7}`O3hLM3mnwf#&F*5^$0xL`fgx<`;z%Z4WfkB0tf#E4={25e+F)}b*VPs(7VqsuN zV`N|mVParNV_;xlWMyEmVP;@Bz|6pKg_(iDo`r#d1M1)HP#R>a6O{dyg@GXq-j0cZVF5D(g9i%(gF7<=12-saLGEK@V2}ZoQA`Zr^&3)1euQdg$VBpIAtM9B zK~VX_#K7fx&{2f#Dw`14AbR1H&su28QR13=CRO_kq^1tcJQ}7S#UBPw&KU+NSpiiKVuvs?FjRu#g_VI}9t#7*9wr6`GbRQGe-_BP&M;;MhQrJZ3=N?0 zXN0WrRcB^kSj5P{5CAnt14>tc^f56oya25eWM*KfW@cdUW@cbm2=X5T1A`0;0|Or; z149thJ)rf2AUD)Q{qc!~0o43ruwY?e_{PG(@PV0uA(x4PA(MfDL6(VuL5!7w;Q=#b zohu6~1H&1pz6*>D47^ab1|tJQE65Mb3=BSu3=E3Ubdki&!0;Iq?ko%pLZH0Oz`$S) zDz6wA7{WkliHU)sn~8xT3F;Tn+I*1P)Mh1rcObiTHq59=m85lH} z85km%7#NCJ7#K`h7#Kc+9KyiBunJTMvM?}Q1eK*M3=CqRc!9bBssx1soex{W!oZ*g zaxWtTLpJE#R;XLVK1z69dCfs60C~Z-EDqKm>3v3q3jtf3=Hp}=E5k@JQ;`$n&)F-f~>~|@xMa#tcTji$jrd7fq{Xco{@oJ zBj}7UMh1qZP&IZ?dryPTmS$mKc*6i$KOV%)z_5#vfgy{9fuW3rfgzijf#Ex7T?r!t z!yc%)uF!Bg0Hwo0`59_%DkB4fBMW5j2*^#1j0_A{nHd;j7#SGmF*7hshMF-M)ZSoZ zVA#jPz);J=z|hLfz@P>-?-tZ;ApK977#LnNF)%oR;ujPTP`N#zwWLf849YCf^V2}} zEU3N8#K4dYRU-kaf0-fc^+9HFfyzx#`Ns^|bM*~WZb99BnvsFw4-*4}5GwxUApe8fiOdWP@{A1N^+v~-85r(C{jwfv#%=}%1__W~7#SEgf!Yd;3=E#2 zvYQFI$AyuBA&!ZG!HAiGVHyhq!yRS@hEiq*1{P2okAZeLFOq z8$fLh(3%1k28NwbF-ArPhAt)shRIO=FGdE24Ip_?xewYW!OXz$0_yL_P#R?Z6%YY( z44%nS_uP(D-%!#&V?3{V@6g@GXp)V_jAfYKZz149}M zWbei%sQ=|y7#O-(7#Q-I7#OlZZf0O$_yelzKxHM=t)MgSn4#|Mgo+ulFfgQm+zK_v z97-cu$M6KIb`L1rp=?n`1_m}J1_m8Q28MX3nIJu&^O@d2&CrI@Gg%lILKzttA{iMN z<}))e%w&e_w+Mjx`3*Az!$(k^%*enX%fi60k(q(vH^?vs28IQo{S3?u46B$J81^zU zFqA>R1!7<`!+7@|S@|CksUETC#uf$AsFna`kh z918=3GbkT2Gl18(q%cGF&4J8TfvN|cQ=iMoz`zVjH&Fk+fx3SO0|Ub+1_lORRtARU zP(Qy1m3zz#4DO)3$H2gForQtnDhmTcBUBz__A~|thKHa&86yLOF(U)RIZ*!#TKDin z)d?~)FxW9NFeF0l1f4(1&&0s+2I{UjW(EcmP&p3epN6VC%)-FX2P!|I{D)Atim);; zOkrYRU}RzdkFkT?F&mWEq58R?bU)O7ko+x128Q#@kUd3x%nS_r%nS_snHd=NvOxBE zfz*KRqyU|f2D%5~7gR4lBLhP@GXn!BsLjO8!0?NSfnhPI?FrJr0NI0fhLM4xn}vZP znUR6v10w@?UFUjGTOZVZhpH20VPLonvJ2`qkZ?Gty~)79kOIn&P``o1L3kO|{>z~J z3zd5hrI$cykU9_+1jQ*M1H%m_28LHmkbQWdyCy(#o}hLN69a=D69dC_CI*IcpgM+y zfguX&4m}nI23|%6h7M>LgVrvGvoJ8+W?*1=4HW~K^MQo{wAGk_3Do~&WMI%ll5;_F zPcRE)|64u_1H&0+$ev`7e$X0c5G@F*2Ur*wQkfYT(wG^*YX`r9Bp4VN=0p7qbHBeAReD+1RCdIgxqT&3d-l8bwi*& zE;9qeT&R0NR-6ZoDM9tW1ht((?S3eqorQtn38;)`hU{krt*Hg+0i7{8orQtnCo=;> zD5!pBVPNQFW?;C$%)pQcO)s4+3=F+cb3k`lY-C|zn9j_=zyYeup!Q#4WMHsjVPH@I zg*&Jp#lXN21C;~W1H$JR85k6p89+xPg7*s4Ff%Y%gW3jAd-S1poMU2O_|3w=uolW^ z294K&%x7j`I0YI*Vu0+W1DQF88M2=d#NGuB?`TlFf`NhI2dF$|W?(2|WMD{OWMI$+ zl@Cxgy&(UA?jK-eV7SM~z;GYx2GCi#AhSSsoVbAc0ieDs3j=sf{6iiv;cT-Tm~a#?kVqlmDwa)?S zN03?&ZenI&NM~eVP-SFbc+bMXu#}mB!H|)G;RFi)Y1q=)fPm%lux<3OX`~%eY z1@$vo7#MU|7#J2ZGcY)S+Pff01_p-5j0_BRptc5*UPDlRVqsvIz|6oP!_2@i9W++J z!octr)L#SL%K_>)BB>7mjo-2`fY;E2j1^{LU~pt&V3@+f0N$@>0?KSOpa3eDq2kY>G-!SOd`1R_ODqfwuFMP!yioP8p!6e9 zxG*pF)-|5WMI$*l>saa3^y1U7%Z6?!0YQ*f$DW;1_sdH#NAN)SAxd4pmtsZ zjZK2`0jNx4Vqj2&*8S0-dJ>dhm>3vtGcz#cLF01?)NPWC3=ABgwgMvqLknme4|F#K zGXukAM#y;rAjd8T^*NyGL3@-Rf$9wg1_o`YJ5De#fcJ=k?*9Pobrfc00Po2J>AeeT z3$rjV)G#tItbn?80caeGg@NHZ)GfQAbRQ!F!)rzc@V3w=KWMBI)PIEf zK^N*j(4HkX&{!v^Ze?O%h+|}6IK<2V-Wvj1KNbNR4~NG`c_Rq|~;Lpgw@D1b+1_p-1ObiTnKw}-CelIHng9+3<;vhGI%6BL~ z3uY1M3;<>ZhWk){J19Rx*;Al)%Ypj%Q2%UWVqkCsmHVLfI}-!LR~80_4WRI6WMJTf zs)1@}5MW_o*aX_E%*?0plW_G zL(W#nW?^7>3aXPp>%&25iiv^2oQZ+K6Evp6$iVO)REIM$Foc8pARso(QBe8=s2l*b zpFrdK%nS^ytPBk6K;zq>bxEKz-$89m76yi8Ape5;{EU#Z0d$xc7+e`4`^LeWs6qWH zXc(-7x)EeW5GY@;FfiO?VPH7I%)l^(nSr5_iGg7*)K8#&Ix9d5LG?S7ZU&8efy#eS z_=4tgSQ!|qq3WSZ!24WIF)%Q2g8J%A3=H|q3=B&c7#QZTFfhciFfcrWDFo39DfuNZ z%%IAks*#*unpdKkqM)i#lv%)FG;3e6OS z{4@nsjgtJ5#2n2O9Ks5jC8@az#i==|$t9_H6%`|^%1*7+ELKp}C`-&KP1P(`D9Efx z&0$d0z$y-MQc->mNL@~9S!#}gss@+_JF2uOQ?pnhCo?Zwp(I~HRU<7Eq>w>X&nQhH zJ2NLgsj?)s7{bj>O;3b!Qxrf922}`M3}V0oNueY^Um+(yFC9g+7*#kwr!+SYtN_dc zn*g#}AuYc&F9jq4;uRxt^NVu9!udtHVAUC^i7A;7OQ1}!Fep4h>OeGDpdhsL1G>#DHJOdCl{rr<}qlf!d#?@#4grk&`8NIP0C4CNY2Sj z&emkmC@IP;KyVGfDYKZtP*1@nwK%&ZzktC=Pr)a#0K~FMva?CbOt%Xx%`8!HF3Bj( z$tbnA(FY0H=qK56afM`L7Aurz=Hw_8m*f{HB!URTMYB9)skP4^#qLkDkIIk!% zGbbli!80!fWKcemL}q$MNnUC(T%&V-4no>FKd+=HvA6_gj&o6daj|YjVkX=G=hC8L zgnEz4g47~#X2Gz@JGC+?Kd~r9!6&gYzZ7nwZ)r|RrfzP2US>&tkwS24Nl9j2I@~b< zMfvGPsl~+#PKiYdp#>?4NIncG%Fip!OU?v`i-JpLGAMi!iz;Dm4Jge^E-8h``hfB^ zOd=Runq=nZVFpKVNn%lnLRwLNt`$sm2q*EO6? z%*jm817#qXF=44iN%_T@C2;3O<>%)@Bgo#~p21PU(K$54mBCTL*)zyF)Yr|&HG;uW z0VLoaDak(OTs)s>N0tN>2%Ngy|-=7FLl1!P1?X=08-a7j^SUOIzgN{T{KetvdtVo|mp zgJVirVqS8pLQZB`szOm}Iw-me@^dmvQbCDbp%{|T;ObJ~Ne`woMNdzU!7(SbsD!~W zCkKQ<0UZwt>0%fU%uy)MNX=77%!{v72*^xH&&*T64EvlMWQTyNsuECjlAo5w;Fwbq z?*k@-KxArBUSdfqgJYgTYEe;skwSiQa%oXfYKophSY~QDI3ytwIr-@dpb$z)ElJGG zDb{0f%*)ILr*;O%yuAEUkmr+Ab8-~oLB)S+5keH~-pc&aB8B**(v*};Q2Z99DwI?f zfP)bc!3>T?iAkBs3hqUTDX9vE430%b`Q;3bB_)Z;8KATcVnT`?1;51HR0hY=l6>d< z+=84`kPk{r@YmyDi!jJ6!NST zz$T$QJnFC593Tc_CIVr^q zPVqUVsa6b5sp*+{d7vDcpQcchU#`dCl$w*CS(>ZhQd*Ln0r#d;W=>{aYGM(CQ+}R; zYjQ?DgA+7af$S_wRY=TL@Kh+zEXhzPN-Zu(O$Ns$IGXZG6beAO98^*>K#E|6WKe-> z1>+TGR)L(7Us95vtKgBClg8i#VF!T!Xa%RtJW#z}%-~d% znwYIn45>CU^Gfm+k~88<^RkN-l2S{`K^dhWv9vf9q%bozK8?Yt2xJ2&^;0;w%aEM{;{EGUlm$xqG(u|UN*gEQFa;N%Vq z*yQ}&q>{0dOcNlH~nttd#$OG!=9V{lH*$pI4zs>KkxxF9hP)cz~VFE7?i0Yx^X zumUwO$vJ1_=NG3IflMjQ&GSf2OaXIp zlkyp0IW`59mU40wl0jYqdnP}x1XR^!7K6hT+!O#;vI_CwO3{h|);s{Q3M#?rOF<)9 zQ^ClXw zRR~HgNln&KaMW|xV{pzd%}G(n%P&z#%gjqrfF(j$PS9gOG=)I%nO|guEK-~q56b4y zrXK^8R&WCu*sQ;QV5Q!9(%Dg%mA(^5e>C>5(1xa0>Vc4&bb3~tLR z1cBpKL0`ca(q;t3F;*3z<|U?@cx1O|6l+?+os(ItkPM3dd~h-cC+6hDqSO*SWEG(H zg+g(DT1k0gQL429sC-XO1T`sAGK-`cvNTfBmKFKdFQAjOIg_x6>Tac5PnxasiSX7jl zS5m2vpT_0u8szNZ=ojMX82rT{Rl@FsMibjD6CUt4Qj9E<(KFvlow@|fQnR*SzNf{PzPLm=qR`qCFW)4 zWafdIeyOP?Itp%?X(bs7ZaMk+MLJwg`Nbvqc?!Oc3JL~BhK2^ZhQ&Sp^72Zx^ro9Nq#N^gi|$p;09 zLLR6bhIRx~i;&tF&Q+jJBdmeul30@JngZ%cF}S2A7o{c^L#=^oh1B8@>-5l+KpPST znI*{?IOK{FOHx5nsYMC_iAC8AE|5Mpj8+J)%qz)A1qDSBTr3IP(f~EmRErs0Qi~Hy zNBo2|fL<$9navM})re&ssybCIBAfq07s9K3oo)4~s5@Ahx zMB^Q^?XJh*0#Oa^w}Cn=B??9P`MIE~JsC8JppctdTnuVGXJi&bLJO`5+`dNAl9vcd zhc5Y`@=&2XF%R6z&B;#(6;gTm<(Q3j7wDJ~gG+viLcBSIvH(%V3g(~=Qi_5FgG*6j zd1hX^V^L}%gA2CykU}!3!31j7VV5pWEdkelpcay93fv437t)}@Gyq8srW?}u1GQ^h zp&f5m1*DF*s{*9c?WzFnWxIxWFu10qrz+$o7R9G$=2zKM&MSb_MrbA?=c!R0Utis0U_9qN$6A4v#RPi$iiMG?(TtyD+_b%|<3Y77niyONr$-3-1E+(S^I#LOav=zFeoHdD#RCqdIfpOsTdOF`9&${g2@?) z@z9}is0(1`fK=mjHA-yYR0WG2oC|1VQNqN$N|0Tk4q`@XVi9;G3>J2J3JM|l3aJ&DB?<_gI-ml( z7*dR<7AGebq=NKAErE0yK{|>RkemRq65@_xB(vbIfErYSVVfRAV>r>BmyeK z8QgLb)6-K^7~JynO5n!l=Y!^J-10%gfThK$ptf*6*aikS&`biPvIVuXl2g&U^4LU; z7(i{ds#FkFSelxbT&bW@oSF>kL%5aZLYZ%<1Wex*ms1Ut4 zbx%#s&IdIlaP&l=eFO&g)S}$PJm_eS0V>xJm21S{o|9Ny3~nE|=Yx_BVgM1s2RFQ6 zg79$=JqCzuK~ZX1W`1cgeB2R5MQX7^N`85sLVjMV0%#--q$?GaV$w>`#UNd0G=(Mk z3OR|zCCDR(P$Nq6AuYnhyyT4hA~eAyP>wDv%?GvB-19*VK&Wa+vj|N!d|C=a95k?z zlwW}^4jY9*6Hm=6DXK&hOUp0Hg^a&VPY#Skhk0Z-mw5yub$_jf>p$7nJIiA9O&MTrF&XyQeQDVh18 zUS3Il9-35fDo9faMtp(GJ~XwcGhS$tWk}OwXi}hB1R(@Zp6KZWE`cqrASA&}cPz$X zNi%Rw;L#({C>=I^m}v*D4=w$`#j&L!xFp_mgsuvUgD}$*Tod**g^)%`S4hGbX$wUT zn;Q@l6j)?INd_&Q!41To*5J}u(i>b3EzQBjaiu%B0_XRHnz_YvbZG%f;hvw8R0%49ic(YK^Q;)$i&9gwp>>lX19Th~L}lisGk9dCq$(80 zgGWjg3i2~S!_5pHpz(f$j*{FQ(5P!-W?pI$gGWhj4!H7y&$}{sLc24b3P{} z6V{#a4EBeN0w@?O6lY|nl`w!i)F46uGC}T{1{Fb6z~1X7U%ip{)qg_Km# zBw30cwBZWsLllA9AIbT7X_-a2dSG42i3KI4MX4!P3aZ7pRr=04bosV`XWeF@Kn;1^Jorp!{pa;G18Tst^xrkwdwl(j_ky z!YRpDh={U6y&3trsYs*GIMspuj?_%VuMo5r4OHZV zQY{`o!^4IcgW-yaG#q5NLShmqjevp+Hs1#l#^WTAv_ev9PCjI123B35Rc{L5`FYT+ zTVi=)C3t}mxUmD%kPA=9dJKNh6+V8cpb@jORE3PvRA?pbms$)RK7e$Z82nN}Q(B;A zY%$s*2EWvDNX9NnOaf&=5FZ>ApxPW!tmh^z@dhj|uJ*W(*6#^>fi$Q!) z+YD5;m*%B_<-saJ5+E0VI%bgdh+sMJcsZowQH&5kbU2U&!5s}G0eB}O6iY!JG&C@N-%LIiV zgI|7LDuZ8sQF&@QqA6j3A!3LjVuT@L%;1+_0;=@jO>@6|&_o|-u^1?$1t%Bf=j4E! z2e38-D20~fD!6u?8)pm7$^+!)wnC7{U+$bhmcC~1~trd2BBLKg*r7f2N= zfM+YgNj)bYGytZ@;16va`y)4w{h^Ixe}&+XAb)RH27hP<^oO;U{qu6-D?w8ziP@k$ zm6r}#n+h7=DFrP(11}L^@GnTsgVg4*`C-uD9dxy;9s^|j4%`e205xAhgn}P@T$~{w zF*C0OGUQlL1ZIMQ2Na{AMW|Kzd8x&qU<3(5R`fxandvcr%*+9i5Zj@x3s9p3JaGlB zpCDC50BBtd$P65+zynbrBca0^3;~J7ut`Knp`M?c3o6I*^FYm2kV&vI3~3q+WI%B- zsBmNmNG$>-Dd?~lcrC3$eja>11yVB;+|tuSXaG9}vig=t9U#{vB^GBUBd^oSF90nv z1UIALZUHHTOmKsmEg7k>HC@PRGxGCN!K2rpo(^c~86EHb zoL>ZPtm!e3q7zb?2V@i_7N^3BTqqCJQ3E%C7y>fmOOi9J7y=+|SV$KmQ32e00p+Nq z)FM4pNyzd$J%#{Kp`Ti$kd~j5lV1)h@RLi6F+{7t3s@Nf@^dna5sT*n@(W4}KleKai}RSPaUApc(J{ zA_Zs)1~1!y%tKXz>s08vZm3BRjp3P9iA5=3(~A{C5|hA_UqPuQrA3froLZEd30ill z2UU`oQ=*+_21?=SpxyEznf(`*b{=R@xu_Jflo2V{ z6+;viD%)Wk+fZ9Tjsh1+ z5OYzYBndPh3^D|?F0Htv2)-Z$+9C(9lLQAKai$=apF%o(s9JMVbMuQT6-vQ#*huaG znVk<>qYPTi3MyTS^NSRUAS*T?Q#!DvGV_x2b3xr~sLP8X{n^B#)I>e7c1V$kSV6Cl zSX`VBTF4J7jX}$5LCFbL(1N;|pg@F7n}Q4|$Vp62RY(NIa#3ntNlqnb*$jAHFSO!i z2ucO30kvB}ON27>(m_I?b?Hf^>7bo93ec6vx}YYVLwa6*ZmM2>Q99W4{Gt+&R}iHR zQgsChDv&bJiZ<}VUn>SkIRZ8oInBeDkw8;$5O@L;x$CO{Th#$_s2&4&I0Q1x5|p1` z0;<*-K#Pt*Q#cu*ZWnk!5T0kDYjZ)hh#o^wemQ7YR(`o=iVkQ*tTZ=I0k+sxGX*RU z8f8o^VhE0hto={PECw|XtQdk(mgK;BpaGsdgd}J=PB3Ws7i==DSdSq%u~NY?Cr804 zzS4>zI5{yVRUtkt5wr>i#04$rfvrdcwHV+-BMgu>A80@V!UFp=I5n{-IYS{nDKR;_ zJh3RHm;ox13|&#K2NOsGEw+S6f;z|fkhO#0)=6ewaS5m#0*zB7DuCiBFCC^2NiCvt zh(~=UL@Rj3D+6TD2x$94W>IPis6>HmX2}6>W&v3N+Mx!QhmI{mTHiQj!2`Wk=w^f4 z<{;6$6lgh~57`q`k`LkQMn*